1use core::cell::{Cell, RefCell};
4use core::future::{Future, poll_fn};
5use core::mem::{self, MaybeUninit};
6use core::sync::atomic::{AtomicBool, Ordering};
7use core::task::Poll;
8
9use embassy_sync::blocking_mutex::CriticalSectionMutex;
10use embassy_sync::waitqueue::WakerRegistration;
11
12use crate::control::{self, InResponse, OutResponse, Recipient, Request, RequestType};
13use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
14use crate::types::InterfaceNumber;
15use crate::{Builder, Handler};
16
17pub const USB_CLASS_CDC: u8 = 0x02;
19
20const USB_CLASS_CDC_DATA: u8 = 0x0a;
21const CDC_SUBCLASS_ACM: u8 = 0x02;
22const CDC_PROTOCOL_NONE: u8 = 0x00;
23
24const CS_INTERFACE: u8 = 0x24;
25const CDC_TYPE_HEADER: u8 = 0x00;
26const CDC_TYPE_ACM: u8 = 0x02;
27const CDC_TYPE_UNION: u8 = 0x06;
28
29const REQ_SEND_ENCAPSULATED_COMMAND: u8 = 0x00;
30#[allow(unused)]
31const REQ_GET_ENCAPSULATED_COMMAND: u8 = 0x01;
32const REQ_SET_LINE_CODING: u8 = 0x20;
33const REQ_GET_LINE_CODING: u8 = 0x21;
34const REQ_SET_CONTROL_LINE_STATE: u8 = 0x22;
35
36#[derive(Clone, Debug)]
38pub enum CdcAcmError {
39 NotConnected,
41}
42
43impl core::fmt::Display for CdcAcmError {
44 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 match *self {
46 Self::NotConnected => f.write_str("NotConnected"),
47 }
48 }
49}
50
51impl core::error::Error for CdcAcmError {}
52impl embedded_io_async::Error for CdcAcmError {
53 fn kind(&self) -> embedded_io_async::ErrorKind {
54 match *self {
55 Self::NotConnected => embedded_io_async::ErrorKind::NotConnected,
56 }
57 }
58}
59
60pub struct State<'a> {
62 control: MaybeUninit<Control<'a>>,
63 shared: ControlShared,
64}
65
66impl<'a> Default for State<'a> {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72impl<'a> State<'a> {
73 pub const fn new() -> Self {
75 Self {
76 control: MaybeUninit::uninit(),
77 shared: ControlShared::new(),
78 }
79 }
80}
81
82pub struct CdcAcmClass<'d, D: Driver<'d>> {
95 _comm_ep: D::EndpointIn,
96 _data_if: InterfaceNumber,
97 read_ep: D::EndpointOut,
98 write_ep: D::EndpointIn,
99 control: &'d ControlShared,
100}
101
102struct Control<'a> {
103 comm_if: InterfaceNumber,
104 shared: &'a ControlShared,
105}
106
107struct ControlShared {
109 line_coding: CriticalSectionMutex<Cell<LineCoding>>,
110 dtr: AtomicBool,
111 rts: AtomicBool,
112
113 waker: RefCell<WakerRegistration>,
114 changed: AtomicBool,
115}
116
117impl Default for ControlShared {
118 fn default() -> Self {
119 Self::new()
120 }
121}
122
123impl ControlShared {
124 const fn new() -> Self {
125 ControlShared {
126 dtr: AtomicBool::new(false),
127 rts: AtomicBool::new(false),
128 line_coding: CriticalSectionMutex::new(Cell::new(LineCoding {
129 stop_bits: StopBits::One,
130 data_bits: 8,
131 parity_type: ParityType::None,
132 data_rate: 8_000,
133 })),
134 waker: RefCell::new(WakerRegistration::new()),
135 changed: AtomicBool::new(false),
136 }
137 }
138
139 fn changed(&self) -> impl Future<Output = ()> + '_ {
140 poll_fn(|cx| {
141 if self.changed.load(Ordering::Relaxed) {
142 self.changed.store(false, Ordering::Relaxed);
143 Poll::Ready(())
144 } else {
145 self.waker.borrow_mut().register(cx.waker());
146 Poll::Pending
147 }
148 })
149 }
150}
151
152impl<'a> Control<'a> {
153 fn shared(&mut self) -> &'a ControlShared {
154 self.shared
155 }
156}
157
158impl<'d> Handler for Control<'d> {
159 fn reset(&mut self) {
160 let shared = self.shared();
161 shared.line_coding.lock(|x| x.set(LineCoding::default()));
162 shared.dtr.store(false, Ordering::Relaxed);
163 shared.rts.store(false, Ordering::Relaxed);
164
165 shared.changed.store(true, Ordering::Relaxed);
166 shared.waker.borrow_mut().wake();
167 }
168
169 fn control_out(&mut self, req: control::Request, data: &[u8]) -> Option<OutResponse> {
170 if (req.request_type, req.recipient, req.index)
171 != (RequestType::Class, Recipient::Interface, self.comm_if.0 as u16)
172 {
173 return None;
174 }
175
176 match req.request {
177 REQ_SEND_ENCAPSULATED_COMMAND => {
178 Some(OutResponse::Accepted)
181 }
182 REQ_SET_LINE_CODING if data.len() >= 7 => {
183 let coding = LineCoding {
184 data_rate: u32::from_le_bytes(data[0..4].try_into().unwrap()),
185 stop_bits: data[4].into(),
186 parity_type: data[5].into(),
187 data_bits: data[6],
188 };
189 let shared = self.shared();
190 shared.line_coding.lock(|x| x.set(coding));
191 debug!("Set line coding to: {:?}", coding);
192
193 shared.changed.store(true, Ordering::Relaxed);
194 shared.waker.borrow_mut().wake();
195
196 Some(OutResponse::Accepted)
197 }
198 REQ_SET_CONTROL_LINE_STATE => {
199 let dtr = (req.value & 0x0001) != 0;
200 let rts = (req.value & 0x0002) != 0;
201
202 let shared = self.shared();
203 shared.dtr.store(dtr, Ordering::Relaxed);
204 shared.rts.store(rts, Ordering::Relaxed);
205 debug!("Set dtr {}, rts {}", dtr, rts);
206
207 shared.changed.store(true, Ordering::Relaxed);
208 shared.waker.borrow_mut().wake();
209
210 Some(OutResponse::Accepted)
211 }
212 _ => Some(OutResponse::Rejected),
213 }
214 }
215
216 fn control_in<'a>(&'a mut self, req: Request, buf: &'a mut [u8]) -> Option<InResponse<'a>> {
217 if (req.request_type, req.recipient, req.index)
218 != (RequestType::Class, Recipient::Interface, self.comm_if.0 as u16)
219 {
220 return None;
221 }
222
223 match req.request {
224 REQ_GET_LINE_CODING if req.length == 7 => {
226 debug!("Sending line coding");
227 let coding = self.shared().line_coding.lock(Cell::get);
228 assert!(buf.len() >= 7);
229 buf[0..4].copy_from_slice(&coding.data_rate.to_le_bytes());
230 buf[4] = coding.stop_bits as u8;
231 buf[5] = coding.parity_type as u8;
232 buf[6] = coding.data_bits;
233 Some(InResponse::Accepted(&buf[0..7]))
234 }
235 _ => Some(InResponse::Rejected),
236 }
237 }
238}
239
240impl<'d, D: Driver<'d>> CdcAcmClass<'d, D> {
241 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State<'d>, max_packet_size: u16) -> Self {
244 assert!(builder.control_buf_len() >= 7);
245
246 let mut func = builder.function(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE);
247
248 let mut iface = func.interface();
250 let comm_if = iface.interface_number();
251 let data_if = u8::from(comm_if) + 1;
252 let mut alt = iface.alt_setting(USB_CLASS_CDC, CDC_SUBCLASS_ACM, CDC_PROTOCOL_NONE, None);
253
254 alt.descriptor(
255 CS_INTERFACE,
256 &[
257 CDC_TYPE_HEADER, 0x10,
259 0x01, ],
261 );
262 alt.descriptor(
263 CS_INTERFACE,
264 &[
265 CDC_TYPE_ACM, 0x02, ],
271 );
272 alt.descriptor(
273 CS_INTERFACE,
274 &[
275 CDC_TYPE_UNION, comm_if.into(), data_if, ],
279 );
280
281 let comm_ep = alt.endpoint_interrupt_in(None, 8, 255);
282
283 let mut iface = func.interface();
285 let data_if = iface.interface_number();
286 let mut alt = iface.alt_setting(USB_CLASS_CDC_DATA, 0x00, CDC_PROTOCOL_NONE, None);
287 let read_ep = alt.endpoint_bulk_out(None, max_packet_size);
288 let write_ep = alt.endpoint_bulk_in(None, max_packet_size);
289
290 drop(func);
291
292 let control = state.control.write(Control {
293 shared: &state.shared,
294 comm_if,
295 });
296 builder.handler(control);
297
298 let control_shared = &state.shared;
299
300 CdcAcmClass {
301 _comm_ep: comm_ep,
302 _data_if: data_if,
303 read_ep,
304 write_ep,
305 control: control_shared,
306 }
307 }
308
309 pub fn max_packet_size(&self) -> u16 {
311 self.read_ep.info().max_packet_size
313 }
314
315 pub fn line_coding(&self) -> LineCoding {
318 self.control.line_coding.lock(Cell::get)
319 }
320
321 pub fn dtr(&self) -> bool {
323 self.control.dtr.load(Ordering::Relaxed)
324 }
325
326 pub fn rts(&self) -> bool {
328 self.control.rts.load(Ordering::Relaxed)
329 }
330
331 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
333 self.write_ep.write(data).await
334 }
335
336 pub async fn read_packet(&mut self, data: &mut [u8]) -> Result<usize, EndpointError> {
338 self.read_ep.read(data).await
339 }
340
341 pub async fn wait_connection(&mut self) {
343 self.read_ep.wait_enabled().await;
344 }
345
346 pub fn split(self) -> (Sender<'d, D>, Receiver<'d, D>) {
350 (
351 Sender {
352 write_ep: self.write_ep,
353 control: self.control,
354 },
355 Receiver {
356 read_ep: self.read_ep,
357 control: self.control,
358 },
359 )
360 }
361
362 pub fn split_with_control(self) -> (Sender<'d, D>, Receiver<'d, D>, ControlChanged<'d>) {
367 (
368 Sender {
369 write_ep: self.write_ep,
370 control: self.control,
371 },
372 Receiver {
373 read_ep: self.read_ep,
374 control: self.control,
375 },
376 ControlChanged { control: self.control },
377 )
378 }
379}
380
381pub struct ControlChanged<'d> {
385 control: &'d ControlShared,
386}
387
388impl<'d> ControlChanged<'d> {
389 pub async fn control_changed(&self) {
391 self.control.changed().await;
392 }
393
394 pub fn dtr(&self) -> bool {
396 self.control.dtr.load(Ordering::Relaxed)
397 }
398
399 pub fn rts(&self) -> bool {
401 self.control.rts.load(Ordering::Relaxed)
402 }
403}
404
405pub struct Sender<'d, D: Driver<'d>> {
409 write_ep: D::EndpointIn,
410 control: &'d ControlShared,
411}
412
413impl<'d, D: Driver<'d>> Sender<'d, D> {
414 pub fn max_packet_size(&self) -> u16 {
416 self.write_ep.info().max_packet_size
418 }
419
420 pub fn line_coding(&self) -> LineCoding {
423 self.control.line_coding.lock(Cell::get)
424 }
425
426 pub fn dtr(&self) -> bool {
428 self.control.dtr.load(Ordering::Relaxed)
429 }
430
431 pub fn rts(&self) -> bool {
433 self.control.rts.load(Ordering::Relaxed)
434 }
435
436 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
438 self.write_ep.write(data).await
439 }
440
441 pub async fn wait_connection(&mut self) {
443 self.write_ep.wait_enabled().await;
444 }
445}
446
447impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for Sender<'d, D> {
448 type Error = CdcAcmError;
449}
450
451impl<'d, D: Driver<'d>> embedded_io_async::Write for Sender<'d, D> {
452 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
453 let len = core::cmp::min(buf.len(), self.max_packet_size() as usize);
454 match self.write_packet(&buf[..len]).await {
455 Ok(()) => Ok(len),
456 Err(EndpointError::BufferOverflow) => unreachable!(),
457 Err(EndpointError::Disabled) => Err(CdcAcmError::NotConnected),
458 }
459 }
460
461 async fn flush(&mut self) -> Result<(), Self::Error> {
462 Ok(())
463 }
464}
465
466pub struct Receiver<'d, D: Driver<'d>> {
470 read_ep: D::EndpointOut,
471 control: &'d ControlShared,
472}
473
474impl<'d, D: Driver<'d>> Receiver<'d, D> {
475 pub fn max_packet_size(&self) -> u16 {
477 self.read_ep.info().max_packet_size
479 }
480
481 pub fn line_coding(&self) -> LineCoding {
484 self.control.line_coding.lock(Cell::get)
485 }
486
487 pub fn dtr(&self) -> bool {
489 self.control.dtr.load(Ordering::Relaxed)
490 }
491
492 pub fn rts(&self) -> bool {
494 self.control.rts.load(Ordering::Relaxed)
495 }
496
497 pub async fn read_packet(&mut self, data: &mut [u8]) -> Result<usize, EndpointError> {
500 self.read_ep.read(data).await
501 }
502
503 pub async fn wait_connection(&mut self) {
505 self.read_ep.wait_enabled().await;
506 }
507
508 pub fn into_buffered(self, buf: &'d mut [u8]) -> BufferedReceiver<'d, D> {
512 BufferedReceiver {
513 receiver: self,
514 buffer: buf,
515 start: 0,
516 end: 0,
517 }
518 }
519}
520
521pub struct BufferedReceiver<'d, D: Driver<'d>> {
535 receiver: Receiver<'d, D>,
536 buffer: &'d mut [u8],
537 start: usize,
538 end: usize,
539}
540
541impl<'d, D: Driver<'d>> BufferedReceiver<'d, D> {
542 fn read_from_buffer(&mut self, buf: &mut [u8]) -> usize {
543 let available = &self.buffer[self.start..self.end];
544 let len = core::cmp::min(available.len(), buf.len());
545 buf[..len].copy_from_slice(&available[..len]);
546 self.start += len;
547 len
548 }
549
550 pub fn line_coding(&self) -> LineCoding {
553 self.receiver.line_coding()
554 }
555
556 pub fn dtr(&self) -> bool {
558 self.receiver.dtr()
559 }
560
561 pub fn rts(&self) -> bool {
563 self.receiver.rts()
564 }
565
566 pub async fn wait_connection(&mut self) {
568 self.receiver.wait_connection().await;
569 }
570}
571
572impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for BufferedReceiver<'d, D> {
573 type Error = CdcAcmError;
574}
575
576impl<'d, D: Driver<'d>> embedded_io_async::Read for BufferedReceiver<'d, D> {
577 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
578 if self.start != self.end {
580 return Ok(self.read_from_buffer(buf));
581 }
582
583 if buf.len() > self.receiver.max_packet_size() as usize {
586 return match self.receiver.read_packet(buf).await {
587 Ok(n) => Ok(n),
588 Err(EndpointError::BufferOverflow) => unreachable!(),
589 Err(EndpointError::Disabled) => Err(CdcAcmError::NotConnected),
590 };
591 }
592
593 match self.receiver.read_packet(&mut self.buffer).await {
598 Ok(n) => self.end = n,
599 Err(EndpointError::BufferOverflow) => unreachable!(),
600 Err(EndpointError::Disabled) => return Err(CdcAcmError::NotConnected),
601 }
602 self.start = 0;
603 return Ok(self.read_from_buffer(buf));
604 }
605}
606
607#[derive(Copy, Clone, Debug, PartialEq, Eq)]
609#[cfg_attr(feature = "defmt", derive(defmt::Format))]
610pub enum StopBits {
611 One = 0,
613
614 OnePointFive = 1,
616
617 Two = 2,
619}
620
621impl From<u8> for StopBits {
622 fn from(value: u8) -> Self {
623 if value <= 2 {
624 unsafe { mem::transmute(value) }
625 } else {
626 StopBits::One
627 }
628 }
629}
630
631#[derive(Copy, Clone, Debug, PartialEq, Eq)]
633#[cfg_attr(feature = "defmt", derive(defmt::Format))]
634pub enum ParityType {
635 None = 0,
637 Odd = 1,
639 Even = 2,
641 Mark = 3,
643 Space = 4,
645}
646
647impl From<u8> for ParityType {
648 fn from(value: u8) -> Self {
649 if value <= 4 {
650 unsafe { mem::transmute(value) }
651 } else {
652 ParityType::None
653 }
654 }
655}
656
657#[derive(Clone, Copy, Debug)]
662#[cfg_attr(feature = "defmt", derive(defmt::Format))]
663pub struct LineCoding {
664 stop_bits: StopBits,
665 data_bits: u8,
666 parity_type: ParityType,
667 data_rate: u32,
668}
669
670impl LineCoding {
671 pub fn stop_bits(&self) -> StopBits {
673 self.stop_bits
674 }
675
676 pub const fn data_bits(&self) -> u8 {
678 self.data_bits
679 }
680
681 pub const fn parity_type(&self) -> ParityType {
683 self.parity_type
684 }
685
686 pub const fn data_rate(&self) -> u32 {
688 self.data_rate
689 }
690}
691
692impl Default for LineCoding {
693 fn default() -> Self {
694 LineCoding {
695 stop_bits: StopBits::One,
696 data_bits: 8,
697 parity_type: ParityType::None,
698 data_rate: 8_000,
699 }
700 }
701}