aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/usb
diff options
context:
space:
mode:
authorkorbin <[email protected]>2025-07-13 20:30:26 -0600
committerkorbin <[email protected]>2025-07-13 20:40:54 -0600
commitb666a88ab175043d711c97b67b5b4d3bf409f102 (patch)
tree02436ff11d08664b4a12aa9b5f2c915f012ba13d /embassy-stm32/src/usb
parent9651cfca51a273ba46d34ce8197fc0e63389b09e (diff)
make usb endpoint allocator methods accept an optional EndpointAddress
Diffstat (limited to 'embassy-stm32/src/usb')
-rw-r--r--embassy-stm32/src/usb/otg.rs8
-rw-r--r--embassy-stm32/src/usb/usb.rs56
2 files changed, 51 insertions, 13 deletions
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs
index 590d1a427..3547ded00 100644
--- a/embassy-stm32/src/usb/otg.rs
+++ b/embassy-stm32/src/usb/otg.rs
@@ -231,19 +231,23 @@ impl<'d, T: Instance> embassy_usb_driver::Driver<'d> for Driver<'d, T> {
231 fn alloc_endpoint_in( 231 fn alloc_endpoint_in(
232 &mut self, 232 &mut self,
233 ep_type: EndpointType, 233 ep_type: EndpointType,
234 ep_addr: Option<EndpointAddress>,
234 max_packet_size: u16, 235 max_packet_size: u16,
235 interval_ms: u8, 236 interval_ms: u8,
236 ) -> Result<Self::EndpointIn, EndpointAllocError> { 237 ) -> Result<Self::EndpointIn, EndpointAllocError> {
237 self.inner.alloc_endpoint_in(ep_type, max_packet_size, interval_ms) 238 self.inner
239 .alloc_endpoint_in(ep_type, ep_addr, max_packet_size, interval_ms)
238 } 240 }
239 241
240 fn alloc_endpoint_out( 242 fn alloc_endpoint_out(
241 &mut self, 243 &mut self,
242 ep_type: EndpointType, 244 ep_type: EndpointType,
245 ep_addr: Option<EndpointAddress>,
243 max_packet_size: u16, 246 max_packet_size: u16,
244 interval_ms: u8, 247 interval_ms: u8,
245 ) -> Result<Self::EndpointOut, EndpointAllocError> { 248 ) -> Result<Self::EndpointOut, EndpointAllocError> {
246 self.inner.alloc_endpoint_out(ep_type, max_packet_size, interval_ms) 249 self.inner
250 .alloc_endpoint_out(ep_type, ep_addr, max_packet_size, interval_ms)
247 } 251 }
248 252
249 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { 253 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 3e8e74a1f..05c28aceb 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -362,6 +362,7 @@ impl<'d, T: Instance> Driver<'d, T> {
362 fn alloc_endpoint<D: Dir>( 362 fn alloc_endpoint<D: Dir>(
363 &mut self, 363 &mut self,
364 ep_type: EndpointType, 364 ep_type: EndpointType,
365 ep_addr: Option<EndpointAddress>,
365 max_packet_size: u16, 366 max_packet_size: u16,
366 interval_ms: u8, 367 interval_ms: u8,
367 ) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> { 368 ) -> Result<Endpoint<'d, T, D>, driver::EndpointAllocError> {
@@ -373,25 +374,56 @@ impl<'d, T: Instance> Driver<'d, T> {
373 D::dir() 374 D::dir()
374 ); 375 );
375 376
376 let index = self.alloc.iter_mut().enumerate().find(|(i, ep)| { 377 let index = if let Some(addr) = ep_addr {
377 if *i == 0 && ep_type != EndpointType::Control { 378 // Use the specified endpoint address
378 return false; // reserved for control pipe 379 let requested_index = addr.index();
380 if requested_index >= EP_COUNT {
381 return Err(EndpointAllocError);
379 } 382 }
383 if requested_index == 0 && ep_type != EndpointType::Control {
384 return Err(EndpointAllocError); // EP0 is reserved for control
385 }
386
387 let ep = &self.alloc[requested_index];
380 let used = ep.used_out || ep.used_in; 388 let used = ep.used_out || ep.used_in;
381 if used && (ep.ep_type == EndpointType::Isochronous) { 389 if used && (ep.ep_type == EndpointType::Isochronous) {
382 // Isochronous endpoints are always double-buffered. 390 // Isochronous endpoints are always double-buffered.
383 // Their corresponding endpoint/channel registers are forced to be unidirectional. 391 // Their corresponding endpoint/channel registers are forced to be unidirectional.
384 // Do not reuse this index. 392 // Do not reuse this index.
385 // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation. 393 return Err(EndpointAllocError);
386 return false;
387 } 394 }
388 395
389 let used_dir = match D::dir() { 396 let used_dir = match D::dir() {
390 Direction::Out => ep.used_out, 397 Direction::Out => ep.used_out,
391 Direction::In => ep.used_in, 398 Direction::In => ep.used_in,
392 }; 399 };
393 !used || (ep.ep_type == ep_type && !used_dir) 400 if used && (ep.ep_type != ep_type || used_dir) {
394 }); 401 return Err(EndpointAllocError);
402 }
403
404 Some((requested_index, &mut self.alloc[requested_index]))
405 } else {
406 // Find any available endpoint
407 self.alloc.iter_mut().enumerate().find(|(i, ep)| {
408 if *i == 0 && ep_type != EndpointType::Control {
409 return false; // reserved for control pipe
410 }
411 let used = ep.used_out || ep.used_in;
412 if used && (ep.ep_type == EndpointType::Isochronous) {
413 // Isochronous endpoints are always double-buffered.
414 // Their corresponding endpoint/channel registers are forced to be unidirectional.
415 // Do not reuse this index.
416 // FIXME: Bulk endpoints can be double buffered, but are not in the current implementation.
417 return false;
418 }
419
420 let used_dir = match D::dir() {
421 Direction::Out => ep.used_out,
422 Direction::In => ep.used_in,
423 };
424 !used || (ep.ep_type == ep_type && !used_dir)
425 })
426 };
395 427
396 let (index, ep) = match index { 428 let (index, ep) = match index {
397 Some(x) => x, 429 Some(x) => x,
@@ -479,27 +511,29 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
479 fn alloc_endpoint_in( 511 fn alloc_endpoint_in(
480 &mut self, 512 &mut self,
481 ep_type: EndpointType, 513 ep_type: EndpointType,
514 ep_addr: Option<EndpointAddress>,
482 max_packet_size: u16, 515 max_packet_size: u16,
483 interval_ms: u8, 516 interval_ms: u8,
484 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> { 517 ) -> Result<Self::EndpointIn, driver::EndpointAllocError> {
485 self.alloc_endpoint(ep_type, max_packet_size, interval_ms) 518 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
486 } 519 }
487 520
488 fn alloc_endpoint_out( 521 fn alloc_endpoint_out(
489 &mut self, 522 &mut self,
490 ep_type: EndpointType, 523 ep_type: EndpointType,
524 ep_addr: Option<EndpointAddress>,
491 max_packet_size: u16, 525 max_packet_size: u16,
492 interval_ms: u8, 526 interval_ms: u8,
493 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> { 527 ) -> Result<Self::EndpointOut, driver::EndpointAllocError> {
494 self.alloc_endpoint(ep_type, max_packet_size, interval_ms) 528 self.alloc_endpoint(ep_type, ep_addr, max_packet_size, interval_ms)
495 } 529 }
496 530
497 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { 531 fn start(mut self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
498 let ep_out = self 532 let ep_out = self
499 .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) 533 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
500 .unwrap(); 534 .unwrap();
501 let ep_in = self 535 let ep_in = self
502 .alloc_endpoint(EndpointType::Control, control_max_packet_size, 0) 536 .alloc_endpoint(EndpointType::Control, None, control_max_packet_size, 0)
503 .unwrap(); 537 .unwrap();
504 assert_eq!(ep_out.info.addr.index(), 0); 538 assert_eq!(ep_out.info.addr.index(), 0);
505 assert_eq!(ep_in.info.addr.index(), 0); 539 assert_eq!(ep_in.info.addr.index(), 0);