aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-03-28 03:19:07 +0200
committerDario Nieuwenhuis <[email protected]>2022-04-06 05:38:11 +0200
commit15cc97d794d8b4baa6c1a8f1ed6c64468701c9e7 (patch)
treeb22553ce22bc8012f04151c08ab8b1d80a127a5c /examples
parent3412e5dc4a771c33dc8db644ba82c071ea486d6d (diff)
usb: associate ControlHandlers with interfaces, automatically route requests.
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf/src/bin/usb/cdc_acm.rs53
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};
3use core::sync::atomic::{AtomicBool, Ordering}; 3use core::sync::atomic::{AtomicBool, Ordering};
4use defmt::info; 4use defmt::info;
5use embassy::blocking_mutex::CriticalSectionMutex; 5use embassy::blocking_mutex::CriticalSectionMutex;
6use embassy_usb::class::{ControlInRequestStatus, RequestStatus, UsbClass}; 6use embassy_usb::class::{ControlHandler, ControlInRequestStatus, RequestStatus};
7use embassy_usb::control::{self, Request}; 7use embassy_usb::control::{self, Request};
8use embassy_usb::driver::{Endpoint, EndpointIn, EndpointOut, ReadError, WriteError}; 8use embassy_usb::driver::{Endpoint, EndpointIn, EndpointOut, ReadError, WriteError};
9use embassy_usb::{driver::Driver, types::*, UsbDeviceBuilder}; 9use embassy_usb::{driver::Driver, types::*, UsbDeviceBuilder};
@@ -64,7 +64,6 @@ pub struct CdcAcmClass<'d, D: Driver<'d>> {
64} 64}
65 65
66struct Control { 66struct 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}
83impl UsbClass for Control { 82impl 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,