aboutsummaryrefslogtreecommitdiff
path: root/embassy-usb/src/builder.rs
diff options
context:
space:
mode:
authorelagil <[email protected]>2024-09-05 21:29:24 +0200
committerelagil <[email protected]>2024-09-05 21:29:24 +0200
commita8ca6713e6e9b7ad5dd53f9b46bcf5e893adda1e (patch)
tree6d8a1eeae8d5b30239ccb1e17be8da19821eb96d /embassy-usb/src/builder.rs
parentd37c482e2179c95740bb4284f4df30637551199b (diff)
feat(usb): make use of ISO endpoint support
Diffstat (limited to 'embassy-usb/src/builder.rs')
-rw-r--r--embassy-usb/src/builder.rs140
1 files changed, 125 insertions, 15 deletions
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 7168e077c..e1bf8041f 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -1,8 +1,8 @@
1use heapless::Vec; 1use heapless::Vec;
2 2
3use crate::config::MAX_HANDLER_COUNT; 3use crate::config::MAX_HANDLER_COUNT;
4use crate::descriptor::{BosWriter, DescriptorWriter}; 4use crate::descriptor::{BosWriter, DescriptorWriter, SynchronizationType, UsageType};
5use crate::driver::{Driver, Endpoint, EndpointType}; 5use crate::driver::{Driver, Endpoint, EndpointInfo, EndpointType};
6use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; 6use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter};
7use crate::types::{InterfaceNumber, StringIndex}; 7use crate::types::{InterfaceNumber, StringIndex};
8use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; 8use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START};
@@ -414,7 +414,7 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
414 /// Descriptors are written in the order builder functions are called. Note that some 414 /// Descriptors are written in the order builder functions are called. Note that some
415 /// classes care about the order. 415 /// classes care about the order.
416 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) { 416 pub fn descriptor(&mut self, descriptor_type: u8, descriptor: &[u8]) {
417 self.builder.config_descriptor.write(descriptor_type, descriptor); 417 self.builder.config_descriptor.write(descriptor_type, descriptor, &[]);
418 } 418 }
419 419
420 /// Add a custom Binary Object Store (BOS) descriptor to this alternate setting. 420 /// Add a custom Binary Object Store (BOS) descriptor to this alternate setting.
@@ -422,26 +422,80 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
422 self.builder.bos_descriptor.capability(capability_type, capability); 422 self.builder.bos_descriptor.capability(capability_type, capability);
423 } 423 }
424 424
425 fn endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn { 425 /// Write a custom endpoint descriptor for a certain endpoint.
426 ///
427 /// This can be necessary, if the endpoint descriptors can only be written
428 /// after the endpoint was created. As an example, an endpoint descriptor
429 /// may contain the address of an endpoint that was allocated earlier.
430 pub fn endpoint_descriptor(
431 &mut self,
432 endpoint: &EndpointInfo,
433 synchronization_type: SynchronizationType,
434 usage_type: UsageType,
435 extra_fields: &[u8],
436 ) {
437 self.builder
438 .config_descriptor
439 .endpoint(endpoint, synchronization_type, usage_type, extra_fields);
440 }
441
442 /// Allocate an IN endpoint, without writing its descriptor.
443 ///
444 /// Used for granular control over the order of endpoint and descriptor creation.
445 pub fn alloc_endpoint_in(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
426 let ep = self 446 let ep = self
427 .builder 447 .builder
428 .driver 448 .driver
429 .alloc_endpoint_in(ep_type, max_packet_size, interval_ms) 449 .alloc_endpoint_in(ep_type, max_packet_size, interval_ms)
430 .expect("alloc_endpoint_in failed"); 450 .expect("alloc_endpoint_in failed");
431 451
432 self.builder.config_descriptor.endpoint(ep.info()); 452 ep
453 }
454
455 fn endpoint_in(
456 &mut self,
457 ep_type: EndpointType,
458 max_packet_size: u16,
459 interval_ms: u8,
460 synchronization_type: SynchronizationType,
461 usage_type: UsageType,
462 extra_fields: &[u8],
463 ) -> D::EndpointIn {
464 let ep = self.alloc_endpoint_in(ep_type, max_packet_size, interval_ms);
465 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
433 466
434 ep 467 ep
435 } 468 }
436 469
437 fn endpoint_out(&mut self, ep_type: EndpointType, max_packet_size: u16, interval_ms: u8) -> D::EndpointOut { 470 /// Allocate an OUT endpoint, without writing its descriptor.
471 ///
472 /// Use for granular control over the order of endpoint and descriptor creation.
473 pub fn alloc_endpoint_out(
474 &mut self,
475 ep_type: EndpointType,
476 max_packet_size: u16,
477 interval_ms: u8,
478 ) -> D::EndpointOut {
438 let ep = self 479 let ep = self
439 .builder 480 .builder
440 .driver 481 .driver
441 .alloc_endpoint_out(ep_type, max_packet_size, interval_ms) 482 .alloc_endpoint_out(ep_type, max_packet_size, interval_ms)
442 .expect("alloc_endpoint_out failed"); 483 .expect("alloc_endpoint_out failed");
443 484
444 self.builder.config_descriptor.endpoint(ep.info()); 485 ep
486 }
487
488 fn endpoint_out(
489 &mut self,
490 ep_type: EndpointType,
491 max_packet_size: u16,
492 interval_ms: u8,
493 synchronization_type: SynchronizationType,
494 usage_type: UsageType,
495 extra_fields: &[u8],
496 ) -> D::EndpointOut {
497 let ep = self.alloc_endpoint_out(ep_type, max_packet_size, interval_ms);
498 self.endpoint_descriptor(ep.info(), synchronization_type, usage_type, extra_fields);
445 499
446 ep 500 ep
447 } 501 }
@@ -451,7 +505,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
451 /// Descriptors are written in the order builder functions are called. Note that some 505 /// Descriptors are written in the order builder functions are called. Note that some
452 /// classes care about the order. 506 /// classes care about the order.
453 pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn { 507 pub fn endpoint_bulk_in(&mut self, max_packet_size: u16) -> D::EndpointIn {
454 self.endpoint_in(EndpointType::Bulk, max_packet_size, 0) 508 self.endpoint_in(
509 EndpointType::Bulk,
510 max_packet_size,
511 0,
512 SynchronizationType::NoSynchronization,
513 UsageType::DataEndpoint,
514 &[],
515 )
455 } 516 }
456 517
457 /// Allocate a BULK OUT endpoint and write its descriptor. 518 /// Allocate a BULK OUT endpoint and write its descriptor.
@@ -459,7 +520,14 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
459 /// Descriptors are written in the order builder functions are called. Note that some 520 /// Descriptors are written in the order builder functions are called. Note that some
460 /// classes care about the order. 521 /// classes care about the order.
461 pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut { 522 pub fn endpoint_bulk_out(&mut self, max_packet_size: u16) -> D::EndpointOut {
462 self.endpoint_out(EndpointType::Bulk, max_packet_size, 0) 523 self.endpoint_out(
524 EndpointType::Bulk,
525 max_packet_size,
526 0,
527 SynchronizationType::NoSynchronization,
528 UsageType::DataEndpoint,
529 &[],
530 )
463 } 531 }
464 532
465 /// Allocate a INTERRUPT IN endpoint and write its descriptor. 533 /// Allocate a INTERRUPT IN endpoint and write its descriptor.
@@ -467,24 +535,66 @@ impl<'a, 'd, D: Driver<'d>> InterfaceAltBuilder<'a, 'd, D> {
467 /// Descriptors are written in the order builder functions are called. Note that some 535 /// Descriptors are written in the order builder functions are called. Note that some
468 /// classes care about the order. 536 /// classes care about the order.
469 pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn { 537 pub fn endpoint_interrupt_in(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn {
470 self.endpoint_in(EndpointType::Interrupt, max_packet_size, interval_ms) 538 self.endpoint_in(
539 EndpointType::Interrupt,
540 max_packet_size,
541 interval_ms,
542 SynchronizationType::NoSynchronization,
543 UsageType::DataEndpoint,
544 &[],
545 )
471 } 546 }
472 547
473 /// Allocate a INTERRUPT OUT endpoint and write its descriptor. 548 /// Allocate a INTERRUPT OUT endpoint and write its descriptor.
474 pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointOut { 549 pub fn endpoint_interrupt_out(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointOut {
475 self.endpoint_out(EndpointType::Interrupt, max_packet_size, interval_ms) 550 self.endpoint_out(
551 EndpointType::Interrupt,
552 max_packet_size,
553 interval_ms,
554 SynchronizationType::NoSynchronization,
555 UsageType::DataEndpoint,
556 &[],
557 )
476 } 558 }
477 559
478 /// Allocate a ISOCHRONOUS IN endpoint and write its descriptor. 560 /// Allocate a ISOCHRONOUS IN endpoint and write its descriptor.
479 /// 561 ///
480 /// Descriptors are written in the order builder functions are called. Note that some 562 /// Descriptors are written in the order builder functions are called. Note that some
481 /// classes care about the order. 563 /// classes care about the order.
482 pub fn endpoint_isochronous_in(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointIn { 564 pub fn endpoint_isochronous_in(
483 self.endpoint_in(EndpointType::Isochronous, max_packet_size, interval_ms) 565 &mut self,
566 max_packet_size: u16,
567 interval_ms: u8,
568 synchronization_type: SynchronizationType,
569 usage_type: UsageType,
570 extra_fields: &[u8],
571 ) -> D::EndpointIn {
572 self.endpoint_in(
573 EndpointType::Isochronous,
574 max_packet_size,
575 interval_ms,
576 synchronization_type,
577 usage_type,
578 extra_fields,
579 )
484 } 580 }
485 581
486 /// Allocate a ISOCHRONOUS OUT endpoint and write its descriptor. 582 /// Allocate a ISOCHRONOUS OUT endpoint and write its descriptor.
487 pub fn endpoint_isochronous_out(&mut self, max_packet_size: u16, interval_ms: u8) -> D::EndpointOut { 583 pub fn endpoint_isochronous_out(
488 self.endpoint_out(EndpointType::Isochronous, max_packet_size, interval_ms) 584 &mut self,
585 max_packet_size: u16,
586 interval_ms: u8,
587 synchronization_type: SynchronizationType,
588 usage_type: UsageType,
589 extra_fields: &[u8],
590 ) -> D::EndpointOut {
591 self.endpoint_out(
592 EndpointType::Isochronous,
593 max_packet_size,
594 interval_ms,
595 synchronization_type,
596 usage_type,
597 extra_fields,
598 )
489 } 599 }
490} 600}