1use super::Request;
2use super::DAP2_PACKET_SIZE;
3use usb_device::class_prelude::*;
4use usb_device::Result;
5
6pub struct CmsisDapV2<'a, B: UsbBus> {
7 interface: InterfaceNumber,
8 name: StringIndex,
9 read_ep: EndpointOut<'a, B>,
10 write_ep: EndpointIn<'a, B>,
11 trace_ep: EndpointIn<'a, B>,
12 trace_busy: bool,
13}
14
15impl<B: UsbBus> CmsisDapV2<'_, B> {
16 pub fn new(max_packet_size: u16, alloc: &UsbBusAllocator<B>) -> CmsisDapV2<B> {
17 CmsisDapV2 {
18 interface: alloc.interface(),
19 name: alloc.string(),
20 read_ep: alloc.bulk(max_packet_size),
21 write_ep: alloc.bulk(max_packet_size),
22 trace_ep: alloc.bulk(max_packet_size),
23 trace_busy: false,
24 }
25 }
26
27 pub fn process(&mut self) -> Option<Request> {
28 let mut buf = [0u8; DAP2_PACKET_SIZE as usize];
29 match self.read_ep.read(&mut buf) {
30 Ok(size) if size > 0 => Some(Request::DAP2Command((buf, size))),
31 _ => None,
32 }
33 }
34
35 pub fn write_packet(&mut self, data: &[u8]) -> Result<()> {
36 if data.len() > self.write_ep.max_packet_size() as usize {
37 return Err(UsbError::BufferOverflow);
38 }
39 self.write_ep.write(&data).map(|_| ())
40 }
41
42 pub fn trace_busy(&self) -> bool {
43 self.trace_busy
44 }
45
46 pub fn trace_write(&mut self, data: &[u8]) -> Result<()> {
47 if data.len() > self.trace_ep.max_packet_size() as usize {
48 return Err(UsbError::BufferOverflow);
49 }
50 self.trace_ep.write(&data).map(|_| ())?;
51 self.trace_busy = true;
52 Ok(())
53 }
54}
55
56impl<B: UsbBus> UsbClass<B> for CmsisDapV2<'_, B> {
57 fn get_configuration_descriptors(&self, writer: &mut DescriptorWriter) -> Result<()> {
58 writer.interface_alt(self.interface, 0, 0xff, 0, 0, Some(self.name))?;
59
60 writer.endpoint(&self.read_ep)?;
61 writer.endpoint(&self.write_ep)?;
62 writer.endpoint(&self.trace_ep)?;
63
64 Ok(())
65 }
66
67 fn get_string(&self, index: StringIndex, _lang_id: LangID) -> Option<&str> {
68 if index == self.name {
69 Some("CMSIS-DAP v2 Interface")
70 } else {
71 None
72 }
73 }
74
75 fn reset(&mut self) {
76 self.trace_busy = false;
77 }
78
79 fn endpoint_in_complete(&mut self, addr: EndpointAddress) {
80 if addr == self.trace_ep.address() {
81 self.trace_busy = false;
82 }
83 }
84}