diff options
Diffstat (limited to 'embassy-usb/src/builder.rs')
| -rw-r--r-- | embassy-usb/src/builder.rs | 140 |
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 @@ | |||
| 1 | use heapless::Vec; | 1 | use heapless::Vec; |
| 2 | 2 | ||
| 3 | use crate::config::MAX_HANDLER_COUNT; | 3 | use crate::config::MAX_HANDLER_COUNT; |
| 4 | use crate::descriptor::{BosWriter, DescriptorWriter}; | 4 | use crate::descriptor::{BosWriter, DescriptorWriter, SynchronizationType, UsageType}; |
| 5 | use crate::driver::{Driver, Endpoint, EndpointType}; | 5 | use crate::driver::{Driver, Endpoint, EndpointInfo, EndpointType}; |
| 6 | use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; | 6 | use crate::msos::{DeviceLevelDescriptor, FunctionLevelDescriptor, MsOsDescriptorWriter}; |
| 7 | use crate::types::{InterfaceNumber, StringIndex}; | 7 | use crate::types::{InterfaceNumber, StringIndex}; |
| 8 | use crate::{Handler, Interface, UsbDevice, MAX_INTERFACE_COUNT, STRING_INDEX_CUSTOM_START}; | 8 | use 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 | } |
