From 52c622b1cd02ba13accc84cd57e90b04797f0405 Mon Sep 17 00:00:00 2001 From: alexmoon Date: Sun, 27 Mar 2022 17:12:57 -0400 Subject: Use trait objects instead of generics for UsbDevice::classes --- examples/nrf/src/bin/usb/cdc_acm.rs | 117 +++++++++++++++--------------------- examples/nrf/src/bin/usb/main.rs | 4 +- 2 files changed, 52 insertions(+), 69 deletions(-) (limited to 'examples/nrf/src') diff --git a/examples/nrf/src/bin/usb/cdc_acm.rs b/examples/nrf/src/bin/usb/cdc_acm.rs index eebf89221..5e4abfea2 100644 --- a/examples/nrf/src/bin/usb/cdc_acm.rs +++ b/examples/nrf/src/bin/usb/cdc_acm.rs @@ -1,4 +1,3 @@ -use core::future::Future; use core::mem; use defmt::info; use embassy_usb::class::{ControlInRequestStatus, RequestStatus, UsbClass}; @@ -56,89 +55,71 @@ pub struct CdcAcmControl { pub rts: bool, } -impl<'d, D: Driver<'d>> UsbClass<'d, D> for CdcAcmControl { - type ControlOutFuture<'a> = impl Future + 'a where Self: 'a, 'd: 'a, D: 'a; - type ControlInFuture<'a> = impl Future + 'a where Self: 'a, 'd: 'a, D: 'a; - +impl UsbClass for CdcAcmControl { fn reset(&mut self) { self.line_coding = LineCoding::default(); self.dtr = false; self.rts = false; } - fn control_out<'a>( - &'a mut self, - req: control::Request, - data: &'a [u8], - ) -> Self::ControlOutFuture<'a> - where - 'd: 'a, - D: 'a, - { - async move { - if !(req.request_type == control::RequestType::Class - && req.recipient == control::Recipient::Interface - && req.index == u8::from(self.comm_if) as u16) - { - return RequestStatus::Unhandled; + fn control_out(&mut self, req: control::Request, data: &[u8]) -> RequestStatus { + if !(req.request_type == control::RequestType::Class + && req.recipient == control::Recipient::Interface + && req.index == u8::from(self.comm_if) as u16) + { + return RequestStatus::Unhandled; + } + + match req.request { + REQ_SEND_ENCAPSULATED_COMMAND => { + // We don't actually support encapsulated commands but pretend we do for standards + // compatibility. + RequestStatus::Accepted } + REQ_SET_LINE_CODING if data.len() >= 7 => { + self.line_coding.data_rate = u32::from_le_bytes(data[0..4].try_into().unwrap()); + self.line_coding.stop_bits = data[4].into(); + self.line_coding.parity_type = data[5].into(); + self.line_coding.data_bits = data[6]; + info!("Set line coding to: {:?}", self.line_coding); + + RequestStatus::Accepted + } + REQ_SET_CONTROL_LINE_STATE => { + self.dtr = (req.value & 0x0001) != 0; + self.rts = (req.value & 0x0002) != 0; + info!("Set dtr {}, rts {}", self.dtr, self.rts); - match req.request { - REQ_SEND_ENCAPSULATED_COMMAND => { - // We don't actually support encapsulated commands but pretend we do for standards - // compatibility. - RequestStatus::Accepted - } - REQ_SET_LINE_CODING if data.len() >= 7 => { - self.line_coding.data_rate = u32::from_le_bytes(data[0..4].try_into().unwrap()); - self.line_coding.stop_bits = data[4].into(); - self.line_coding.parity_type = data[5].into(); - self.line_coding.data_bits = data[6]; - info!("Set line coding to: {:?}", self.line_coding); - - RequestStatus::Accepted - } - REQ_SET_CONTROL_LINE_STATE => { - self.dtr = (req.value & 0x0001) != 0; - self.rts = (req.value & 0x0002) != 0; - info!("Set dtr {}, rts {}", self.dtr, self.rts); - - RequestStatus::Accepted - } - _ => RequestStatus::Rejected, + RequestStatus::Accepted } + _ => RequestStatus::Rejected, } } fn control_in<'a>( - &'a mut self, + &mut self, req: Request, - control: embassy_usb::class::ControlIn<'a, 'd, D>, - ) -> Self::ControlInFuture<'a> - where - 'd: 'a, - { - async move { - if !(req.request_type == control::RequestType::Class - && req.recipient == control::Recipient::Interface - && req.index == u8::from(self.comm_if) as u16) - { - return control.ignore(); - } + control: embassy_usb::class::ControlIn<'a>, + ) -> ControlInRequestStatus<'a> { + if !(req.request_type == control::RequestType::Class + && req.recipient == control::Recipient::Interface + && req.index == u8::from(self.comm_if) as u16) + { + return control.ignore(); + } - match req.request { - // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. - REQ_GET_LINE_CODING if req.length == 7 => { - info!("Sending line coding"); - let mut data = [0; 7]; - data[0..4].copy_from_slice(&self.line_coding.data_rate.to_le_bytes()); - data[4] = self.line_coding.stop_bits as u8; - data[5] = self.line_coding.parity_type as u8; - data[6] = self.line_coding.data_bits; - control.accept(&data).await - } - _ => control.reject(), + match req.request { + // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. + REQ_GET_LINE_CODING if req.length == 7 => { + info!("Sending line coding"); + let mut data = [0; 7]; + data[0..4].copy_from_slice(&self.line_coding.data_rate.to_le_bytes()); + data[4] = self.line_coding.stop_bits as u8; + data[5] = self.line_coding.parity_type as u8; + data[6] = self.line_coding.data_bits; + control.accept(&data) } + _ => control.reject(), } } } diff --git a/examples/nrf/src/bin/usb/main.rs b/examples/nrf/src/bin/usb/main.rs index 71285579c..73ac3a21f 100644 --- a/examples/nrf/src/bin/usb/main.rs +++ b/examples/nrf/src/bin/usb/main.rs @@ -16,6 +16,7 @@ use embassy_nrf::interrupt; use embassy_nrf::pac; use embassy_nrf::usb::Driver; use embassy_nrf::Peripherals; +use embassy_usb::class::UsbClass; use embassy_usb::driver::{EndpointIn, EndpointOut}; use embassy_usb::{Config, UsbDeviceBuilder}; use futures::future::join3; @@ -59,7 +60,8 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut class = CdcAcmClass::new(&mut builder, 64); // Build the builder. - let mut usb = builder.build(class.control); + let mut classes: [&mut dyn UsbClass; 1] = [&mut class.control]; + let mut usb = builder.build(&mut classes); // Run the USB device. let fut1 = usb.run(); -- cgit