probe_rs/probe/cmsisdap/commands/
swo.rs

1use scroll::{LE, Pread};
2
3use super::{CommandId, Request, SendError, Status};
4
5#[repr(u8)]
6#[expect(unused)]
7#[derive(Copy, Clone, Debug)]
8pub enum TransportRequest {
9    NoTransport = 0,
10    DataCommand = 1,
11    WinUsbEndpoint = 2,
12}
13
14impl Request for TransportRequest {
15    const COMMAND_ID: CommandId = CommandId::SwoTransport;
16
17    type Response = TransportResponse;
18
19    fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
20        buffer[0] = *self as u8;
21        Ok(1)
22    }
23
24    fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
25        Ok(TransportResponse {
26            status: Status::from_byte(buffer[0])?,
27        })
28    }
29}
30
31#[derive(Debug)]
32pub struct TransportResponse {
33    pub(crate) status: Status,
34}
35
36#[repr(u8)]
37#[expect(unused)]
38#[derive(Copy, Clone, Debug)]
39pub enum ModeRequest {
40    Off = 0,
41    Uart = 1,
42    Manchester = 2,
43}
44
45impl Request for ModeRequest {
46    const COMMAND_ID: CommandId = CommandId::SwoMode;
47
48    type Response = ModeResponse;
49
50    fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
51        buffer[0] = *self as u8;
52        Ok(1)
53    }
54
55    fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
56        Ok(ModeResponse {
57            status: Status::from_byte(buffer[0])?,
58        })
59    }
60}
61
62#[derive(Debug)]
63pub struct ModeResponse {
64    pub(crate) status: Status,
65}
66
67#[derive(Copy, Clone, Debug)]
68pub struct BaudrateRequest {
69    pub(crate) baudrate: u32,
70}
71
72impl Request for BaudrateRequest {
73    const COMMAND_ID: CommandId = CommandId::SwoBaudrate;
74
75    type Response = u32;
76
77    fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
78        assert!(
79            buffer.len() >= 4,
80            "Buffer for CMSIS-DAP command is too small. This is a bug, please report it."
81        );
82        buffer[0..4].copy_from_slice(&self.baudrate.to_le_bytes());
83        Ok(4)
84    }
85
86    fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
87        if buffer.len() < 4 {
88            return Err(SendError::NotEnoughData);
89        }
90
91        let baud: u32 = buffer
92            .pread_with(0, LE)
93            .map_err(|_| SendError::NotEnoughData)?;
94
95        Ok(baud)
96    }
97}
98
99#[repr(u8)]
100#[derive(Copy, Clone, Debug)]
101pub enum ControlRequest {
102    Stop = 0,
103    Start = 1,
104}
105
106impl Request for ControlRequest {
107    const COMMAND_ID: CommandId = CommandId::SwoControl;
108
109    type Response = ControlResponse;
110
111    fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
112        buffer[0] = *self as u8;
113        Ok(1)
114    }
115
116    fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
117        Ok(ControlResponse {
118            status: Status::from_byte(buffer[0])?,
119        })
120    }
121}
122
123#[derive(Debug)]
124pub struct ControlResponse {
125    pub(crate) status: Status,
126}
127
128#[derive(Debug)]
129pub struct StatusRequest;
130
131impl Request for StatusRequest {
132    const COMMAND_ID: CommandId = CommandId::SwoStatus;
133
134    type Response = StatusResponse;
135
136    fn to_bytes(&self, _buffer: &mut [u8]) -> Result<usize, SendError> {
137        Ok(0)
138    }
139
140    fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
141        let status = TraceStatus::from(buffer[0]);
142        let count = u32::from_le_bytes(
143            buffer[1..5]
144                .try_into()
145                .map_err(|_| SendError::NotEnoughData)?,
146        );
147        Ok(StatusResponse {
148            _status: status,
149            _count: count,
150        })
151    }
152}
153
154#[derive(Copy, Clone, Debug)]
155pub struct TraceStatus {
156    pub(crate) _active: bool,
157    pub(crate) error: bool,
158    pub(crate) _overrun: bool,
159}
160
161impl From<u8> for TraceStatus {
162    fn from(value: u8) -> Self {
163        Self {
164            _active: value & (1 << 0) != 0,
165            error: value & (1 << 6) != 0,
166            _overrun: value & (1 << 7) != 0,
167        }
168    }
169}
170
171#[derive(Debug)]
172pub struct StatusResponse {
173    pub(crate) _status: TraceStatus,
174    pub(crate) _count: u32,
175}
176
177#[derive(Debug)]
178pub struct ExtendedStatusRequest {
179    pub(crate) request_status: bool,
180    pub(crate) request_count: bool,
181    pub(crate) request_index_timestamp: bool,
182}
183
184impl Request for ExtendedStatusRequest {
185    const COMMAND_ID: CommandId = CommandId::SwoExtendedStatus;
186
187    type Response = ExtendedStatusResponse;
188
189    fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
190        let control = (self.request_status as u8)
191            | ((self.request_count as u8) << 1)
192            | ((self.request_index_timestamp as u8) << 2);
193        buffer[0] = control;
194        Ok(1)
195    }
196
197    fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
198        if buffer.len() < 13 {
199            return Err(SendError::NotEnoughData);
200        }
201
202        let status = TraceStatus::from(buffer[0]);
203        let count = u32::from_le_bytes(
204            buffer[1..5]
205                .try_into()
206                .map_err(|_| SendError::NotEnoughData)?,
207        );
208        let index = u32::from_le_bytes(
209            buffer[5..9]
210                .try_into()
211                .map_err(|_| SendError::NotEnoughData)?,
212        );
213        let timestamp = u32::from_le_bytes(
214            buffer[9..13]
215                .try_into()
216                .map_err(|_| SendError::NotEnoughData)?,
217        );
218        Ok(ExtendedStatusResponse {
219            _status: status,
220            _count: count,
221            _index: index,
222            _timestamp: timestamp,
223        })
224    }
225}
226
227#[derive(Debug)]
228pub struct ExtendedStatusResponse {
229    pub(crate) _status: TraceStatus,
230    pub(crate) _count: u32,
231    pub(crate) _index: u32,
232    pub(crate) _timestamp: u32,
233}
234
235#[derive(Debug)]
236pub struct DataRequest {
237    pub(crate) max_count: u16,
238}
239
240impl Request for DataRequest {
241    const COMMAND_ID: CommandId = CommandId::SwoData;
242
243    type Response = DataResponse;
244
245    fn to_bytes(&self, buffer: &mut [u8]) -> Result<usize, SendError> {
246        assert!(
247            buffer.len() >= 2,
248            "Buffer for CMSIS-DAP command is too small. This is a bug, please report it."
249        );
250        buffer[0..2].copy_from_slice(&self.max_count.to_le_bytes());
251        Ok(2)
252    }
253
254    fn parse_response(&self, buffer: &[u8]) -> Result<Self::Response, SendError> {
255        let status = TraceStatus::from(buffer[0]);
256        let count = u16::from_le_bytes(
257            buffer[1..3]
258                .try_into()
259                .map_err(|_| SendError::NotEnoughData)?,
260        );
261        let start = 3;
262        let end = start + count as usize;
263        if end > buffer.len() {
264            return Err(SendError::NotEnoughData);
265        }
266
267        Ok(DataResponse {
268            status,
269            data: buffer[start..end].to_vec(),
270        })
271    }
272}
273
274#[derive(Debug)]
275pub struct DataResponse {
276    pub(crate) status: TraceStatus,
277    pub(crate) data: Vec<u8>,
278}