aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDániel Buga <[email protected]>2025-04-17 18:05:03 +0200
committerDániel Buga <[email protected]>2025-04-17 21:03:58 +0200
commite410e65b830f5486a9d15b87039817aa4668e06f (patch)
tree2246af46352a6d745277502f713142ac54cbd0d9
parent0313089991870357f47ba92f42373b6e7a7160c7 (diff)
Add CMSIS-DAP driver
-rw-r--r--embassy-usb/src/class/cmsis_dap_v2.rs101
-rw-r--r--embassy-usb/src/class/mod.rs1
2 files changed, 102 insertions, 0 deletions
diff --git a/embassy-usb/src/class/cmsis_dap_v2.rs b/embassy-usb/src/class/cmsis_dap_v2.rs
new file mode 100644
index 000000000..41f6be5dd
--- /dev/null
+++ b/embassy-usb/src/class/cmsis_dap_v2.rs
@@ -0,0 +1,101 @@
1//! CMSIS-DAP V2 class implementation.
2
3use core::mem::MaybeUninit;
4
5use crate::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
6use crate::types::StringIndex;
7use crate::{msos, Builder, Handler};
8
9/// State for the CMSIS-DAP v2 USB class.
10pub struct State {
11 control: MaybeUninit<Control>,
12}
13
14struct Control {
15 iface_string: StringIndex,
16}
17
18impl Handler for Control {
19 fn get_string(&mut self, index: StringIndex, _lang_id: u16) -> Option<&str> {
20 if index == self.iface_string {
21 Some("CMSIS-DAP v2 Interface")
22 } else {
23 warn!("unknown string index requested");
24 None
25 }
26 }
27}
28
29impl State {
30 /// Create a new `State`.
31 pub const fn new() -> Self {
32 Self {
33 control: MaybeUninit::uninit(),
34 }
35 }
36}
37
38/// USB device class for CMSIS-DAP v2 probes.
39pub struct CmsisDapV2Class<'d, D: Driver<'d>> {
40 read_ep: D::EndpointOut,
41 write_ep: D::EndpointIn,
42 max_packet_size: u16,
43}
44
45impl<'d, D: Driver<'d>> CmsisDapV2Class<'d, D> {
46 /// Creates a new CmsisDapV2Class with the provided UsbBus and `max_packet_size` in bytes. For
47 /// full-speed devices, `max_packet_size` has to be 64.
48 pub fn new(builder: &mut Builder<'d, D>, state: &'d mut State, max_packet_size: u16) -> Self {
49 // DAP - Custom Class 0
50 let iface_string = builder.string();
51 let mut function = builder.function(0xFF, 0, 0);
52 function.msos_feature(msos::CompatibleIdFeatureDescriptor::new("WINUSB", ""));
53 function.msos_feature(msos::RegistryPropertyFeatureDescriptor::new(
54 "DeviceInterfaceGUIDs",
55 // CMSIS-DAP standard GUID, from https://arm-software.github.io/CMSIS_5/DAP/html/group__DAP__ConfigUSB__gr.html
56 msos::PropertyData::RegMultiSz(&["{CDB3B5AD-293B-4663-AA36-1AAE46463776}"]),
57 ));
58 let mut interface = function.interface();
59 let mut alt = interface.alt_setting(0xFF, 0, 0, Some(iface_string));
60 let read_ep = alt.endpoint_bulk_out(max_packet_size);
61 let write_ep = alt.endpoint_bulk_in(max_packet_size);
62 drop(function);
63
64 builder.handler(state.control.write(Control { iface_string }));
65
66 CmsisDapV2Class {
67 read_ep,
68 write_ep,
69 max_packet_size,
70 }
71 }
72
73 /// Waits for the USB host to enable this interface
74 pub async fn wait_connection(&mut self) {
75 self.read_ep.wait_enabled().await;
76 }
77
78 /// Write data to the host.
79 pub async fn write_packet(&mut self, data: &[u8]) -> Result<(), EndpointError> {
80 for chunk in data.chunks(self.max_packet_size as usize) {
81 self.write_ep.write(chunk).await?;
82 }
83 if data.len() % self.max_packet_size as usize == 0 {
84 self.write_ep.write(&[]).await?;
85 }
86 Ok(())
87 }
88
89 /// Read data from the host.
90 pub async fn read_packet(&mut self, data: &mut [u8]) -> Result<usize, EndpointError> {
91 let mut n = 0;
92
93 loop {
94 let i = self.read_ep.read(&mut data[n..]).await?;
95 n += i;
96 if i < self.max_packet_size as usize {
97 return Ok(n);
98 }
99 }
100 }
101}
diff --git a/embassy-usb/src/class/mod.rs b/embassy-usb/src/class/mod.rs
index 4bd89eb66..c01707971 100644
--- a/embassy-usb/src/class/mod.rs
+++ b/embassy-usb/src/class/mod.rs
@@ -1,6 +1,7 @@
1//! Implementations of well-known USB classes. 1//! Implementations of well-known USB classes.
2pub mod cdc_acm; 2pub mod cdc_acm;
3pub mod cdc_ncm; 3pub mod cdc_ncm;
4pub mod cmsis_dap_v2;
4pub mod hid; 5pub mod hid;
5pub mod midi; 6pub mod midi;
6pub mod uac1; 7pub mod uac1;