Merge pull request #4397 from korbin/allocate-numbered-endpoints

Make USB endpoint allocator methods accept an optional `EndpointAddress`
This commit is contained in:
Dario Nieuwenhuis 2025-07-15 22:08:08 +00:00 committed by GitHub
commit f525386fca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 203 additions and 87 deletions

View File

@ -121,10 +121,11 @@ impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
let index = self.alloc_in.allocate(ep_type)?;
let index = self.alloc_in.allocate(ep_type, ep_addr)?;
let ep_addr = EndpointAddress::from_parts(index, Direction::In);
Ok(Endpoint::new(EndpointInfo {
addr: ep_addr,
@ -137,10 +138,11 @@ impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
let index = self.alloc_out.allocate(ep_type)?;
let index = self.alloc_out.allocate(ep_type, ep_addr)?;
let ep_addr = EndpointAddress::from_parts(index, Direction::Out);
Ok(Endpoint::new(EndpointInfo {
addr: ep_addr,
@ -734,7 +736,11 @@ impl Allocator {
Self { used: 0 }
}
fn allocate(&mut self, ep_type: EndpointType) -> Result<usize, driver::EndpointAllocError> {
fn allocate(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
) -> Result<usize, driver::EndpointAllocError> {
// Endpoint addresses are fixed in hardware:
// - 0x80 / 0x00 - Control EP0
// - 0x81 / 0x01 - Bulk/Interrupt EP1
@ -748,7 +754,27 @@ impl Allocator {
// Endpoint directions are allocated individually.
let alloc_index = match ep_type {
let alloc_index = if let Some(addr) = ep_addr {
// Use the specified endpoint address
let requested_index = addr.index();
// Validate the requested index based on endpoint type
match ep_type {
EndpointType::Isochronous => {
if requested_index != 8 {
return Err(driver::EndpointAllocError);
}
}
EndpointType::Control => return Err(driver::EndpointAllocError),
EndpointType::Interrupt | EndpointType::Bulk => {
if requested_index < 1 || requested_index > 7 {
return Err(driver::EndpointAllocError);
}
}
}
requested_index
} else {
// Allocate any available endpoint
match ep_type {
EndpointType::Isochronous => 8,
EndpointType::Control => return Err(driver::EndpointAllocError),
EndpointType::Interrupt | EndpointType::Bulk => {
@ -759,6 +785,7 @@ impl Allocator {
}
ones + 1
}
}
};
if self.used & (1 << alloc_index) != 0 {

View File

@ -153,6 +153,7 @@ impl<'d, T: Instance> Driver<'d, T> {
fn alloc_endpoint<D: Dir>(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> {
@ -169,12 +170,25 @@ impl<'d, T: Instance> Driver<'d, T> {
Direction::In => &mut self.ep_in,
};
let index = alloc.iter_mut().enumerate().find(|(i, ep)| {
let index = if let Some(addr) = ep_addr {
// Use the specified endpoint address
let requested_index = addr.index();
if requested_index == 0 || requested_index >= EP_COUNT {
return Err(EndpointAllocError);
}
if alloc[requested_index].used {
return Err(EndpointAllocError);
}
Some((requested_index, &mut alloc[requested_index]))
} else {
// Find any available endpoint
alloc.iter_mut().enumerate().find(|(i, ep)| {
if *i == 0 {
return false; // reserved for control pipe
}
!ep.used
});
})
};
let (index, ep) = index.ok_or(EndpointAllocError)?;
assert!(!ep.used);
@ -299,19 +313,21 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {

View File

@ -231,19 +231,23 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, EndpointAllocError> {
self.inner.alloc_endpoint_in(ep_type, max_packet_size, interval_ms)
self.inner
.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, EndpointAllocError> {
self.inner.alloc_endpoint_out(ep_type, max_packet_size, interval_ms)
self.inner
.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {

View File

@ -359,26 +359,19 @@ impl<'d, T: Instance> Driver<'d, T> {
addr
}
fn alloc_endpoint<D: Dir>(
&mut self,
ep_type: EndpointType,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> {
trace!(
"allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
ep_type,
max_packet_size,
interval_ms,
D::dir()
);
let index = self.alloc.iter_mut().enumerate().find(|(i, ep)| {
if *i == 0 && ep_type != EndpointType::Control {
return false; // reserved for control pipe
fn is_endpoint_available<D: Dir>(&self, index: usize, ep_type: EndpointType) -> bool {
if index == 0 && ep_type != EndpointType::Control {
return false; // EP0 is reserved for control
}
let ep = match self.alloc.get(index) {
Some(ep) => ep,
None => return false,
};
let used = ep.used_out || ep.used_in;
if used && (ep.ep_type == EndpointType::Isochronous) {
if used && ep.ep_type == EndpointType::Isochronous {
// Isochronous endpoints are always double-buffered.
// Their corresponding endpoint/channel registers are forced to be unidirectional.
// Do not reuse this index.
@ -390,11 +383,36 @@ impl<'d, T: Instance> Driver<'d, T> {
Direction::Out => ep.used_out,
Direction::In => ep.used_in,
};
!used || (ep.ep_type == ep_type && !used_dir)
});
}
fn alloc_endpoint<D: Dir>(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> {
trace!(
"allocating type={:?} mps={:?} interval_ms={}, dir={:?}",
ep_type,
max_packet_size,
interval_ms,
D::dir()
);
let index = if let Some(addr) = ep_addr {
// Use the specified endpoint address
self.is_endpoint_available::<D>(addr.index(), ep_type)
.then_some(addr.index())
} else {
// Find any available endpoint
(0..self.alloc.len()).find(|&i| self.is_endpoint_available::<D>(i, ep_type))
};
let (index, ep) = match index {
Some(x) => x,
Some(i) => (i, &mut self.alloc[i]),
None => return Err(EndpointAllocError),
};
@ -479,27 +497,29 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
let ep_out = self
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
.alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
.unwrap();
let ep_in = self
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
.alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
.unwrap();
assert_eq!(ep_out.info.addr.index(), 0);
assert_eq!(ep_in.info.addr.index(), 0);

View File

@ -136,6 +136,7 @@ pub trait Driver<'a> {
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, EndpointAllocError>;
@ -153,6 +154,7 @@ pub trait Driver<'a> {
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, EndpointAllocError>;

View File

@ -345,6 +345,7 @@ impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> {
fn alloc_endpoint<D: Dir>(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Endpoint<'d, D>, EndpointAllocError> {
@ -379,15 +380,31 @@ impl<'d, const MAX_EP_COUNT: usize> Driver<'d, MAX_EP_COUNT> {
Direction::In => &mut self.ep_in[..self.instance.endpoint_count],
};
// Find free endpoint slot
let slot = eps.iter_mut().enumerate().find(|(i, ep)| {
// Find endpoint slot
let slot = if let Some(addr) = ep_addr {
// Use the specified endpoint address
let requested_index = addr.index();
if requested_index >= self.instance.endpoint_count {
return Err(EndpointAllocError);
}
if requested_index == 0 && ep_type != EndpointType::Control {
return Err(EndpointAllocError); // EP0 is reserved for control
}
if eps[requested_index].is_some() {
return Err(EndpointAllocError); // Already allocated
}
Some((requested_index, &mut eps[requested_index]))
} else {
// Find any free endpoint slot
eps.iter_mut().enumerate().find(|(i, ep)| {
if *i == 0 && ep_type != EndpointType::Control {
// reserved for control pipe
false
} else {
ep.is_none()
}
});
})
};
let index = match slot {
Some((index, ep)) => {
@ -438,27 +455,29 @@ impl<'d, const MAX_EP_COUNT: usize> embassy_usb_driver::Driver<'d> for Driver<'d
fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointIn, EndpointAllocError> {
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> Result<Self::EndpointOut, EndpointAllocError> {
self.alloc_endpoint(ep_type, max_packet_size, interval_ms)
self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
}
fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
let ep_out = self
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
.alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
.unwrap();
let ep_in = self
.alloc_endpoint(EndpointType::Control, control_max_packet_size, 0)
.alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
.unwrap();
assert_eq!(ep_out.info.addr.index(), 0);
assert_eq!(ep_in.info.addr.index(), 0);

View File

@ -2,7 +2,7 @@ use heapless::Vec;
use crate::config::MAX_HANDLER_COUNT;
use crate::descriptor::{BosWriter, DescriptorWriter, SynchronizationType, UsageType};
use crate::driver::{Driver, Endpoint, EndpointInfo, EndpointType};
use crate::driver::{Driver, Endpoint, EndpointAddress, EndpointInfo, EndpointType};
use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
use crate::types::{InterfaceNumber, StringIndex};
use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
@ -465,11 +465,17 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
/// Allocate an IN endpoint, without writing its descriptor.
///
/// Used for granular control over the order of endpoint and descriptor creation.
pub fn alloc_endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
pub fn alloc_endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> D::EndpointIn {
let ep = self
.builder
.driver
.alloc_endpoint_in(ep_type, max_packet_size, interval_ms)
.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
.expect("alloc_endpoint_in failed");
ep
@ -478,13 +484,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
fn endpoint_in(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
synchronization_type: SynchronizationType,
usage_type: UsageType,
extra_fields: &[u8],
) -> D::EndpointIn {
let ep = self.alloc_endpoint_in(ep_type, max_packet_size, interval_ms);
let ep = self.alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms);
self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
ep
@ -496,13 +503,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
pub fn alloc_endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> D::EndpointOut {
let ep = self
.builder
.driver
.alloc_endpoint_out(ep_type, max_packet_size, interval_ms)
.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
.expect("alloc_endpoint_out failed");
ep
@ -511,13 +519,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
fn endpoint_out(
&mut self,
ep_type: EndpointType,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
synchronization_type: SynchronizationType,
usage_type: UsageType,
extra_fields: &[u8],
) -> D::EndpointOut {
let ep = self.alloc_endpoint_out(ep_type, max_packet_size, interval_ms);
let ep = self.alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms);
self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
ep
@ -527,9 +536,10 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
///
/// Descriptors are written in the order builder functions are called. Note that some
/// classes care about the order.
pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn {
pub fn endpoint_bulk_in(&mut self, ep_addr: Option<EndpointAddress>, max_packet_size: u16) -> D::EndpointIn {
self.endpoint_in(
EndpointType::Bulk,
ep_addr,
max_packet_size,
0,
SynchronizationType::NoSynchronization,
@ -542,9 +552,10 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
///
/// Descriptors are written in the order builder functions are called. Note that some
/// classes care about the order.
pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut {
pub fn endpoint_bulk_out(&mut self, ep_addr: Option<EndpointAddress>, max_packet_size: u16) -> D::EndpointOut {
self.endpoint_out(
EndpointType::Bulk,
ep_addr,
max_packet_size,
0,
SynchronizationType::NoSynchronization,
@ -557,9 +568,15 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
///
/// Descriptors are written in the order builder functions are called. Note that some
/// classes care about the order.
pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
pub fn endpoint_interrupt_in(
&mut self,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> D::EndpointIn {
self.endpoint_in(
EndpointType::Interrupt,
ep_addr,
max_packet_size,
interval_ms,
SynchronizationType::NoSynchronization,
@ -569,9 +586,15 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
}
/// Allocate a INTERRUPT OUT endpoint and write its descriptor.
pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointOut {
pub fn endpoint_interrupt_out(
&mut self,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
) -> D::EndpointOut {
self.endpoint_out(
EndpointType::Interrupt,
ep_addr,
max_packet_size,
interval_ms,
SynchronizationType::NoSynchronization,
@ -586,6 +609,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
/// classes care about the order.
pub fn endpoint_isochronous_in(
&mut self,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
synchronization_type: SynchronizationType,
@ -594,6 +618,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
) -> D::EndpointIn {
self.endpoint_in(
EndpointType::Isochronous,
ep_addr,
max_packet_size,
interval_ms,
synchronization_type,
@ -605,6 +630,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
/// Allocate a ISOCHRONOUS OUT endpoint and write its descriptor.
pub fn endpoint_isochronous_out(
&mut self,
ep_addr: Option<EndpointAddress>,
max_packet_size: u16,
interval_ms: u8,
synchronization_type: SynchronizationType,
@ -613,6 +639,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
) -> D::EndpointOut {
self.endpoint_out(
EndpointType::Isochronous,
ep_addr,
max_packet_size,
interval_ms,
synchronization_type,

View File

@ -254,14 +254,14 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
],
);
let comm_ep = alt.endpoint_interrupt_in(8, 255);
let comm_ep = alt.endpoint_interrupt_in(None, 8, 255);
// Data interface
let mut iface = func.interface();
let data_if = iface.interface_number();
let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NONE, None);
let read_ep = alt.endpoint_bulk_out(max_packet_size);
let write_ep = alt.endpoint_bulk_in(max_packet_size);
let read_ep = alt.endpoint_bulk_out(None, max_packet_size);
let write_ep = alt.endpoint_bulk_in(None, max_packet_size);
drop(func);

View File

@ -313,15 +313,15 @@ impl<'d, D: Driver<'d>> CdcNcmClass<'d, D> {
],
);
let comm_ep = alt.endpoint_interrupt_in(8, 255);
let comm_ep = alt.endpoint_interrupt_in(None, 8, 255);
// Data interface
let mut iface = func.interface();
let data_if = iface.interface_number();
let _alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None);
let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NTB, None);
let read_ep = alt.endpoint_bulk_out(max_packet_size);
let write_ep = alt.endpoint_bulk_in(max_packet_size);
let read_ep = alt.endpoint_bulk_out(None, max_packet_size);
let write_ep = alt.endpoint_bulk_in(None, max_packet_size);
drop(func);

View File

@ -61,10 +61,10 @@ impl<'d, D: Driver<'d>> CmsisDapV2Class<'d, D> {
));
let mut interface = function.interface();
let mut alt = interface.alt_setting(0xFF, 0, 0, Some(iface_string));
let read_ep = alt.endpoint_bulk_out(max_packet_size);
let write_ep = alt.endpoint_bulk_in(max_packet_size);
let read_ep = alt.endpoint_bulk_out(None, max_packet_size);
let write_ep = alt.endpoint_bulk_in(None, max_packet_size);
let trace_ep = if trace {
Some(alt.endpoint_bulk_in(max_packet_size))
Some(alt.endpoint_bulk_in(None, max_packet_size))
} else {
None
};

View File

@ -133,9 +133,9 @@ fn build<'d, D: Driver<'d>>(
],
);
let ep_in = alt.endpoint_interrupt_in(config.max_packet_size, config.poll_ms);
let ep_in = alt.endpoint_interrupt_in(None, config.max_packet_size, config.poll_ms);
let ep_out = if with_out_endpoint {
Some(alt.endpoint_interrupt_out(config.max_packet_size, config.poll_ms))
Some(alt.endpoint_interrupt_out(None, config.max_packet_size, config.poll_ms))
} else {
None
};

View File

@ -129,14 +129,14 @@ impl<'d, D: Driver<'d>> MidiClass<'d, D> {
for i in 0..n_out_jacks {
endpoint_data[2 + i as usize] = in_jack_id_emb(i);
}
let read_ep = alt.endpoint_bulk_out(max_packet_size);
let read_ep = alt.endpoint_bulk_out(None, max_packet_size);
alt.descriptor(CS_ENDPOINT, &endpoint_data[0..2 + n_out_jacks as usize]);
endpoint_data[1] = n_in_jacks;
for i in 0..n_in_jacks {
endpoint_data[2 + i as usize] = out_jack_id_emb(i);
}
let write_ep = alt.endpoint_bulk_in(max_packet_size);
let write_ep = alt.endpoint_bulk_in(None, max_packet_size);
alt.descriptor(CS_ENDPOINT, &endpoint_data[0..2 + n_in_jacks as usize]);
MidiClass { read_ep, write_ep }

View File

@ -268,9 +268,10 @@ impl<'d, D: Driver<'d>> Speaker<'d, D> {
alt.descriptor(CS_INTERFACE, &format_descriptor);
let streaming_endpoint = alt.alloc_endpoint_out(EndpointType::Isochronous, max_packet_size, 1);
let streaming_endpoint = alt.alloc_endpoint_out(EndpointType::Isochronous, None, max_packet_size, 1);
let feedback_endpoint = alt.alloc_endpoint_in(
EndpointType::Isochronous,
None,
4, // Feedback packets are 24 bit (10.14 format).
1,
);

View File

@ -96,8 +96,8 @@ async fn main(_spawner: Spawner) {
let mut function = builder.function(0xFF, 0, 0);
let mut interface = function.interface();
let mut alt = interface.alt_setting(0xFF, 0, 0, None);
let mut read_ep = alt.endpoint_bulk_out(64);
let mut write_ep = alt.endpoint_bulk_in(64);
let mut read_ep = alt.endpoint_bulk_out(None, 64);
let mut write_ep = alt.endpoint_bulk_in(None, 64);
drop(function);
// Build the builder.

View File

@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> {
let mut iface = func.interface();
let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None);
let write_ep = alt.endpoint_bulk_in(config.max_packet_size);
let read_ep = alt.endpoint_bulk_out(config.max_packet_size);
let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size);
let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size);
WebEndpoints { write_ep, read_ep }
}

View File

@ -125,8 +125,8 @@ impl<'d, D: Driver<'d>> WebEndpoints<'d, D> {
let mut iface = func.interface();
let mut alt = iface.alt_setting(0xff, 0x00, 0x00, None);
let write_ep = alt.endpoint_bulk_in(config.max_packet_size);
let read_ep = alt.endpoint_bulk_out(config.max_packet_size);
let write_ep = alt.endpoint_bulk_in(None, config.max_packet_size);
let read_ep = alt.endpoint_bulk_out(None, config.max_packet_size);
WebEndpoints { write_ep, read_ep }
}