diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-03-28 03:19:07 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-04-06 05:38:11 +0200 |
| commit | 15cc97d794d8b4baa6c1a8f1ed6c64468701c9e7 (patch) | |
| tree | b22553ce22bc8012f04151c08ab8b1d80a127a5c /examples | |
| parent | 3412e5dc4a771c33dc8db644ba82c071ea486d6d (diff) | |
usb: associate ControlHandlers with interfaces, automatically route requests.
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/nrf/src/bin/usb/cdc_acm.rs | 53 |
1 files changed, 18 insertions, 35 deletions
diff --git a/examples/nrf/src/bin/usb/cdc_acm.rs b/examples/nrf/src/bin/usb/cdc_acm.rs index 92cc16eb4..f4d429792 100644 --- a/examples/nrf/src/bin/usb/cdc_acm.rs +++ b/examples/nrf/src/bin/usb/cdc_acm.rs | |||
| @@ -3,7 +3,7 @@ use core::mem::{self, MaybeUninit}; | |||
| 3 | use core::sync::atomic::{AtomicBool, Ordering}; | 3 | use core::sync::atomic::{AtomicBool, Ordering}; |
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy::blocking_mutex::CriticalSectionMutex; | 5 | use embassy::blocking_mutex::CriticalSectionMutex; |
| 6 | use embassy_usb::class::{ControlInRequestStatus, RequestStatus, UsbClass}; | 6 | use embassy_usb::class::{ControlHandler, ControlInRequestStatus, RequestStatus}; |
| 7 | use embassy_usb::control::{self, Request}; | 7 | use embassy_usb::control::{self, Request}; |
| 8 | use embassy_usb::driver::{Endpoint, EndpointIn, EndpointOut, ReadError, WriteError}; | 8 | use embassy_usb::driver::{Endpoint, EndpointIn, EndpointOut, ReadError, WriteError}; |
| 9 | use embassy_usb::{driver::Driver, types::*, UsbDeviceBuilder}; | 9 | use embassy_usb::{driver::Driver, types::*, UsbDeviceBuilder}; |
| @@ -64,7 +64,6 @@ pub struct CdcAcmClass<'d, D: Driver<'d>> { | |||
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | struct Control { | 66 | struct Control { |
| 67 | comm_if: InterfaceNumber, | ||
| 68 | shared: UnsafeCell<ControlShared>, | 67 | shared: UnsafeCell<ControlShared>, |
| 69 | } | 68 | } |
| 70 | 69 | ||
| @@ -80,7 +79,7 @@ impl Control { | |||
| 80 | unsafe { &*(self.shared.get() as *const _) } | 79 | unsafe { &*(self.shared.get() as *const _) } |
| 81 | } | 80 | } |
| 82 | } | 81 | } |
| 83 | impl UsbClass for Control { | 82 | impl ControlHandler for Control { |
| 84 | fn reset(&mut self) { | 83 | fn reset(&mut self) { |
| 85 | let shared = self.shared(); | 84 | let shared = self.shared(); |
| 86 | shared.line_coding.lock(|x| x.set(LineCoding::default())); | 85 | shared.line_coding.lock(|x| x.set(LineCoding::default())); |
| @@ -89,13 +88,6 @@ impl UsbClass for Control { | |||
| 89 | } | 88 | } |
| 90 | 89 | ||
| 91 | fn control_out(&mut self, req: control::Request, data: &[u8]) -> RequestStatus { | 90 | fn control_out(&mut self, req: control::Request, data: &[u8]) -> RequestStatus { |
| 92 | if !(req.request_type == control::RequestType::Class | ||
| 93 | && req.recipient == control::Recipient::Interface | ||
| 94 | && req.index == u8::from(self.comm_if) as u16) | ||
| 95 | { | ||
| 96 | return RequestStatus::Unhandled; | ||
| 97 | } | ||
| 98 | |||
| 99 | match req.request { | 91 | match req.request { |
| 100 | REQ_SEND_ENCAPSULATED_COMMAND => { | 92 | REQ_SEND_ENCAPSULATED_COMMAND => { |
| 101 | // We don't actually support encapsulated commands but pretend we do for standards | 93 | // We don't actually support encapsulated commands but pretend we do for standards |
| @@ -134,13 +126,6 @@ impl UsbClass for Control { | |||
| 134 | req: Request, | 126 | req: Request, |
| 135 | control: embassy_usb::class::ControlIn<'a>, | 127 | control: embassy_usb::class::ControlIn<'a>, |
| 136 | ) -> ControlInRequestStatus<'a> { | 128 | ) -> ControlInRequestStatus<'a> { |
| 137 | if !(req.request_type == control::RequestType::Class | ||
| 138 | && req.recipient == control::Recipient::Interface | ||
| 139 | && req.index == u8::from(self.comm_if) as u16) | ||
| 140 | { | ||
| 141 | return control.ignore(); | ||
| 142 | } | ||
| 143 | |||
| 144 | match req.request { | 129 | match req.request { |
| 145 | // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. | 130 | // REQ_GET_ENCAPSULATED_COMMAND is not really supported - it will be rejected below. |
| 146 | REQ_GET_LINE_CODING if req.length == 7 => { | 131 | REQ_GET_LINE_CODING if req.length == 7 => { |
| @@ -166,7 +151,22 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 166 | state: &'d mut State, | 151 | state: &'d mut State, |
| 167 | max_packet_size: u16, | 152 | max_packet_size: u16, |
| 168 | ) -> Self { | 153 | ) -> Self { |
| 169 | let comm_if = builder.alloc_interface(); | 154 | let control = state.control.write(Control { |
| 155 | shared: UnsafeCell::new(ControlShared { | ||
| 156 | dtr: AtomicBool::new(false), | ||
| 157 | rts: AtomicBool::new(false), | ||
| 158 | line_coding: CriticalSectionMutex::new(Cell::new(LineCoding { | ||
| 159 | stop_bits: StopBits::One, | ||
| 160 | data_bits: 8, | ||
| 161 | parity_type: ParityType::None, | ||
| 162 | data_rate: 8_000, | ||
| 163 | })), | ||
| 164 | }), | ||
| 165 | }); | ||
| 166 | |||
| 167 | let control_shared = unsafe { &*(control.shared.get() as *const _) }; | ||
| 168 | |||
| 169 | let comm_if = builder.alloc_interface_with_handler(control); | ||
| 170 | let comm_ep = builder.alloc_interrupt_endpoint_in(8, 255); | 170 | let comm_ep = builder.alloc_interrupt_endpoint_in(8, 255); |
| 171 | let data_if = builder.alloc_interface(); | 171 | let data_if = builder.alloc_interface(); |
| 172 | let read_ep = builder.alloc_bulk_endpoint_out(max_packet_size); | 172 | let read_ep = builder.alloc_bulk_endpoint_out(max_packet_size); |
| @@ -245,23 +245,6 @@ impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> { | |||
| 245 | builder.config_descriptor.endpoint(write_ep.info()).unwrap(); | 245 | builder.config_descriptor.endpoint(write_ep.info()).unwrap(); |
| 246 | builder.config_descriptor.endpoint(read_ep.info()).unwrap(); | 246 | builder.config_descriptor.endpoint(read_ep.info()).unwrap(); |
| 247 | 247 | ||
| 248 | let control = state.control.write(Control { | ||
| 249 | comm_if, | ||
| 250 | shared: UnsafeCell::new(ControlShared { | ||
| 251 | dtr: AtomicBool::new(false), | ||
| 252 | rts: AtomicBool::new(false), | ||
| 253 | line_coding: CriticalSectionMutex::new(Cell::new(LineCoding { | ||
| 254 | stop_bits: StopBits::One, | ||
| 255 | data_bits: 8, | ||
| 256 | parity_type: ParityType::None, | ||
| 257 | data_rate: 8_000, | ||
| 258 | })), | ||
| 259 | }), | ||
| 260 | }); | ||
| 261 | |||
| 262 | let control_shared = unsafe { &*(control.shared.get() as *const _) }; | ||
| 263 | builder.add_class(control); | ||
| 264 | |||
| 265 | CdcAcmClass { | 248 | CdcAcmClass { |
| 266 | comm_ep, | 249 | comm_ep, |
| 267 | data_if, | 250 | data_if, |
