dap_rs/
dap.rs

1use crate::{jtag, swd, swj, swo, usb};
2
3mod command;
4mod request;
5mod response;
6mod state;
7
8pub use command::*;
9pub use request::*;
10pub use response::*;
11
12pub use embedded_hal::delay::DelayNs;
13
14use state::State;
15
16/// LED control trait.
17pub trait DapLeds {
18    /// React to host status, usually setting some LEDs
19    fn react_to_host_status(&mut self, host_status: HostStatus);
20}
21
22/// DAP handler.
23pub struct Dap<'a, DEPS, LEDS, WAIT, JTAG, SWD, SWO> {
24    state: State<DEPS, SWD, JTAG>,
25    swo: Option<SWO>,
26    swo_streaming: bool,
27    swd_wait_retries: usize,
28    match_retries: usize,
29    version_string: &'a str,
30    // mode: Option<DapMode>,
31    leds: LEDS,
32    wait: WAIT,
33}
34
35impl<'a, DEPS, LEDS, WAIT, JTAG, SWD, SWO> Dap<'a, DEPS, LEDS, WAIT, JTAG, SWD, SWO>
36where
37    DEPS: swj::Dependencies<SWD, JTAG>,
38    LEDS: DapLeds,
39    WAIT: DelayNs,
40    JTAG: jtag::Jtag<DEPS>,
41    SWD: swd::Swd<DEPS>,
42    SWO: swo::Swo,
43{
44    /// Create a Dap handler
45    pub fn new(
46        dependencies: DEPS,
47        leds: LEDS,
48        wait: WAIT,
49        swo: Option<SWO>,
50        version_string: &'a str,
51    ) -> Self {
52        // TODO: Replace with const assert
53        assert!(SWD::AVAILABLE || JTAG::AVAILABLE);
54
55        Dap {
56            state: State::new(dependencies),
57            swo,
58            swo_streaming: false,
59            swd_wait_retries: 5,
60            match_retries: 8,
61            version_string,
62            // mode: None,
63            leds,
64            wait,
65        }
66    }
67
68    /// Process a new CMSIS-DAP command from `report`.
69    ///
70    /// Returns number of bytes written to response buffer.
71    pub fn process_command(
72        &mut self,
73        report: &[u8],
74        rbuf: &mut [u8],
75        version: DapVersion,
76    ) -> usize {
77        let req = match Request::from_report(report) {
78            Some(req) => req,
79            None => return 0,
80        };
81
82        let resp = &mut ResponseWriter::new(req.command, rbuf);
83
84        // defmt::trace!("Dap command: {}", req.command);
85
86        match req.command {
87            Command::DAP_Info => self.process_info(req, resp, version),
88            Command::DAP_HostStatus => self.process_host_status(req, resp),
89            Command::DAP_Connect => self.process_connect(req, resp),
90            Command::DAP_Disconnect => self.process_disconnect(req, resp),
91            Command::DAP_WriteABORT => self.process_write_abort(req, resp),
92            Command::DAP_Delay => self.process_delay(req, resp),
93            Command::DAP_ResetTarget => self.process_reset_target(req, resp),
94            Command::DAP_SWJ_Pins => self.process_swj_pins(req, resp),
95            Command::DAP_SWJ_Clock => self.process_swj_clock(req, resp),
96            Command::DAP_SWJ_Sequence => self.process_swj_sequence(req, resp),
97            Command::DAP_SWD_Configure => self.process_swd_configure(req, resp),
98            Command::DAP_SWD_Sequence => self.process_swd_sequence(req, resp),
99            Command::DAP_SWO_Transport => self.process_swo_transport(req, resp),
100            Command::DAP_SWO_Mode => self.process_swo_mode(req, resp),
101            Command::DAP_SWO_Baudrate => self.process_swo_baudrate(req, resp),
102            Command::DAP_SWO_Control => self.process_swo_control(req, resp),
103            Command::DAP_SWO_Status => self.process_swo_status(req, resp),
104            Command::DAP_SWO_ExtendedStatus => self.process_swo_extended_status(req, resp),
105            Command::DAP_SWO_Data => self.process_swo_data(req, resp),
106            Command::DAP_JTAG_Configure => self.process_jtag_configure(req, resp),
107            Command::DAP_JTAG_IDCODE => self.process_jtag_idcode(req, resp),
108            Command::DAP_JTAG_Sequence => self.process_jtag_sequence(req, resp),
109            Command::DAP_TransferConfigure => self.process_transfer_configure(req, resp),
110            Command::DAP_Transfer => self.process_transfer(req, resp),
111            Command::DAP_TransferBlock => self.process_transfer_block(req, resp),
112            Command::DAP_TransferAbort => {
113                self.process_transfer_abort();
114                // Do not send a response for transfer abort commands
115                return 0;
116            }
117            Command::DAP_ExecuteCommands => self.process_execute_commands(req, resp),
118            Command::DAP_QueueCommands => self.process_queue_commands(req, resp),
119            Command::Unimplemented => {}
120        }
121
122        resp.idx
123    }
124
125    /// Suspend the interface.
126    pub fn suspend(&mut self) {
127        self.state.to_none();
128
129        if let State::None { deps, .. } = &mut self.state {
130            deps.high_impedance_mode();
131        } else {
132            unreachable!();
133        }
134    }
135
136    fn process_info(&mut self, mut req: Request, resp: &mut ResponseWriter, version: DapVersion) {
137        match DapInfoID::try_from(req.next_u8()) {
138            // Return 0-length string for VendorID, ProductID, SerialNumber
139            // to indicate they should be read from USB descriptor instead
140            Ok(DapInfoID::VendorID) => resp.write_u8(0),
141            Ok(DapInfoID::ProductID) => resp.write_u8(0),
142            Ok(DapInfoID::SerialNumber) => resp.write_u8(0),
143            // Return git version as firmware version
144            Ok(DapInfoID::FirmwareVersion) => {
145                resp.write_u8(self.version_string.len() as u8);
146                resp.write_slice(self.version_string.as_bytes());
147            }
148            // Return 0-length string for TargetVendor and TargetName to indicate
149            // unknown target device.
150            Ok(DapInfoID::TargetVendor) => resp.write_u8(0),
151            Ok(DapInfoID::TargetName) => resp.write_u8(0),
152            Ok(DapInfoID::Capabilities) => {
153                resp.write_u8(1);
154                // Bit 0: SWD supported
155                // Bit 1: JTAG supported
156                // Bit 2: SWO UART supported
157                // Bit 3: SWO Manchester not supported
158                // Bit 4: Atomic commands not supported
159                // Bit 5: Test Domain Timer not supported
160                // Bit 6: SWO Streaming Trace supported
161                let swd = (SWD::AVAILABLE as u8) << 0;
162                let jtag = (JTAG::AVAILABLE as u8) << 1;
163                let swo = match &self.swo {
164                    Some(swo) => {
165                        let support = swo.support();
166                        (support.uart as u8) << 2 | (support.manchester as u8) << 3
167                    }
168                    None => 0,
169                };
170                let atomic = 0 << 4;
171                let swo_streaming = 1 << 6;
172                resp.write_u8(swd | jtag | swo | atomic | swo_streaming);
173            }
174            Ok(DapInfoID::SWOTraceBufferSize) => {
175                resp.write_u8(4);
176                let size = match &self.swo {
177                    Some(swo) => swo.buffer_size(),
178                    None => 0,
179                };
180                resp.write_u32(size as u32);
181            }
182            Ok(DapInfoID::MaxPacketCount) => {
183                resp.write_u8(1);
184                // Maximum of one packet at a time
185                resp.write_u8(1);
186            }
187            Ok(DapInfoID::MaxPacketSize) => {
188                resp.write_u8(2);
189                match version {
190                    DapVersion::V1 => {
191                        // Maximum of 64 bytes per packet
192                        resp.write_u16(usb::DAP1_PACKET_SIZE);
193                    }
194                    DapVersion::V2 => {
195                        // Maximum of 512 bytes per packet
196                        resp.write_u16(usb::DAP2_PACKET_SIZE);
197                    }
198                }
199            }
200            _ => resp.write_u8(0),
201        }
202    }
203
204    fn process_host_status(&mut self, mut req: Request, resp: &mut ResponseWriter) {
205        let status_type = req.next_u8();
206        let status_status = req.next_u8();
207        // Use HostStatus to set our LED when host is connected to target
208        if let Ok(status) = HostStatusType::try_from(status_type) {
209            let status_value = status_status != 0;
210            let status = match status {
211                HostStatusType::Connect => HostStatus::Connected(status_value),
212                HostStatusType::Running => HostStatus::Running(status_value),
213            };
214
215            self.leds.react_to_host_status(status);
216        }
217        resp.write_u8(0);
218    }
219
220    fn process_connect(&mut self, mut req: Request, resp: &mut ResponseWriter) {
221        let port = req.next_u8();
222        let port = match ConnectPort::try_from(port) {
223            Ok(port) => port,
224            Err(_) => {
225                resp.write_u8(ConnectPortResponse::Failed as u8);
226                return;
227            }
228        };
229
230        // defmt::info!(
231        // "DAP connect: {}, SWD: {}, JTAG: {}",
232        // port,
233        // SWD::AVAILABLE,
234        // JTAG::AVAILABLE
235        // );
236
237        match (SWD::AVAILABLE, JTAG::AVAILABLE, port) {
238            // SWD
239            (true, true, ConnectPort::Default)
240            | (true, true, ConnectPort::SWD)
241            | (true, false, ConnectPort::Default)
242            | (true, false, ConnectPort::SWD) => {
243                self.state.to_swd();
244                resp.write_u8(ConnectPortResponse::SWD as u8);
245            }
246
247            // JTAG
248            (true, true, ConnectPort::JTAG)
249            | (false, true, ConnectPort::Default)
250            | (false, true, ConnectPort::JTAG) => {
251                self.state.to_jtag();
252                resp.write_u8(ConnectPortResponse::JTAG as u8);
253            }
254
255            // Error (tried to connect JTAG or SWD when not available)
256            (true, false, ConnectPort::JTAG) | (false, true, ConnectPort::SWD) => {
257                resp.write_u8(ConnectPortResponse::Failed as u8);
258            }
259
260            // Checked by `new`
261            (false, false, _) => unreachable!(),
262        }
263    }
264
265    fn process_disconnect(&mut self, _req: Request, resp: &mut ResponseWriter) {
266        self.state.to_none();
267
268        if let State::None { deps, .. } = &mut self.state {
269            deps.high_impedance_mode();
270        } else {
271            unreachable!();
272        }
273
274        resp.write_ok();
275    }
276
277    fn process_write_abort(&mut self, mut req: Request, resp: &mut ResponseWriter) {
278        self.state.to_last_mode();
279
280        let idx = req.next_u8();
281        let word = req.next_u32();
282        match (SWD::AVAILABLE, JTAG::AVAILABLE, &mut self.state) {
283            (_, true, State::Jtag(_jtag)) => {
284                // TODO: Implement one day.
285                let _ = idx;
286                resp.write_err();
287            }
288            (true, _, State::Swd(swd)) => {
289                match swd.write_dp(self.swd_wait_retries, swd::DPRegister::DPIDR, word) {
290                    Ok(_) => resp.write_ok(),
291                    Err(_) => resp.write_err(),
292                }
293            }
294            _ => {
295                resp.write_err();
296            }
297        }
298    }
299
300    fn process_delay(&mut self, mut req: Request, resp: &mut ResponseWriter) {
301        let delay = req.next_u16() as u32;
302        self.wait.delay_us(delay);
303        resp.write_ok();
304    }
305
306    fn process_reset_target(&mut self, _req: Request, resp: &mut ResponseWriter) {
307        resp.write_ok();
308        // "No device specific reset sequence is implemented"
309        resp.write_u8(0);
310    }
311
312    fn process_swj_pins(&mut self, mut req: Request, resp: &mut ResponseWriter) {
313        let output = swj::Pins::from_bits_truncate(req.next_u8());
314        let mask = swj::Pins::from_bits_truncate(req.next_u8());
315        let wait_us = req.next_u32().min(3_000_000); // Defined as max 3 seconds
316
317        self.state.to_none();
318
319        if let State::None { deps, .. } = &mut self.state {
320            resp.write_u8(deps.process_swj_pins(output, mask, wait_us).bits());
321        } else {
322            unreachable!();
323        }
324    }
325
326    fn process_swj_clock(&mut self, mut req: Request, resp: &mut ResponseWriter) {
327        let max_frequency = req.next_u32();
328        let valid = self.state.set_clock(max_frequency);
329
330        if valid {
331            resp.write_ok();
332        } else {
333            resp.write_err();
334        }
335    }
336
337    fn process_swj_sequence(&mut self, mut req: Request, resp: &mut ResponseWriter) {
338        let nbits: usize = match req.next_u8() {
339            // CMSIS-DAP says 0 means 256 bits
340            0 => 256,
341            // Other integers are normal.
342            n => n as usize,
343        };
344
345        let payload = req.rest();
346        let nbytes = (nbits + 7) / 8;
347        let seq = if nbytes <= payload.len() {
348            &payload[..nbytes]
349        } else {
350            resp.write_err();
351            return;
352        };
353
354        self.state.to_none();
355
356        if let State::None { deps, .. } = &mut self.state {
357            deps.process_swj_sequence(seq, nbits);
358        } else {
359            unreachable!();
360        }
361
362        resp.write_ok();
363    }
364
365    fn process_swd_configure(&mut self, mut req: Request, resp: &mut ResponseWriter) {
366        // TODO: Do we want to support other configs?
367        let config = req.next_u8();
368        let clk_period = config & 0b011;
369        let always_data = (config & 0b100) != 0;
370        if clk_period == 0 && !always_data {
371            resp.write_ok();
372        } else {
373            resp.write_err();
374        }
375    }
376
377    fn process_swd_sequence(&mut self, mut req: Request, resp: &mut ResponseWriter) {
378        self.state.to_swd();
379        let swd = match &mut self.state {
380            State::Swd(swd) => swd,
381            _ => {
382                resp.write_err();
383                return;
384            }
385        };
386
387        resp.write_ok(); // assume ok until we finish
388        let sequence_count = req.next_u8();
389        let success = (0..sequence_count).map(|_| {
390            // parse the seqnence info
391            let sequence_info = req.next_u8();
392            let nbits: usize = match sequence_info & 0x3F {
393                // CMSIS-DAP says 0 means 64 bits
394                0 => 64,
395                // Other integers are normal.
396                n => n as usize,
397            };
398            let nbytes = (nbits + 7) / 8;
399            let output = (sequence_info & 0x80) == 0;
400
401            if output {
402                let output_data = req.data.get(..nbytes).ok_or(())?;
403                swd.write_sequence(nbits, output_data).or(Err(()))?;
404                req.consume(nbytes);
405                Ok(0)
406            } else {
407                let input_data = resp.remaining().get_mut(..nbytes).ok_or(())?;
408                swd.read_sequence(nbits, input_data).or(Err(()))?;
409                resp.skip(nbytes);
410                Ok(nbytes)
411            }
412        }).all(|r: Result<usize, ()>| r.is_ok());
413        
414        if !success {
415            resp.write_u8_at(0, 0xFF);
416        }
417    }
418
419    fn process_swo_transport(&mut self, mut req: Request, resp: &mut ResponseWriter) {
420        let transport = req.next_u8();
421        match swo::SwoTransport::try_from(transport) {
422            Ok(swo::SwoTransport::None) | Ok(swo::SwoTransport::DAPCommand) => {
423                self.swo_streaming = false;
424                resp.write_ok();
425            }
426            Ok(swo::SwoTransport::USBEndpoint) => {
427                self.swo_streaming = true;
428                resp.write_ok();
429            }
430            _ => resp.write_err(),
431        }
432    }
433
434    fn process_swo_mode(&mut self, mut req: Request, resp: &mut ResponseWriter) {
435        let mode = req.next_u8();
436
437        let swo = if let Some(swo) = &mut self.swo {
438            swo
439        } else {
440            resp.write_err();
441            return;
442        };
443
444        match swo::SwoMode::try_from(mode) {
445            Ok(mode) => {
446                swo.set_mode(mode);
447                resp.write_ok();
448            }
449            _ => resp.write_err(),
450        }
451    }
452
453    fn process_swo_baudrate(&mut self, mut req: Request, resp: &mut ResponseWriter) {
454        let target = req.next_u32();
455        let actual = if let Some(swo) = &mut self.swo {
456            swo.set_baudrate(target)
457        } else {
458            0
459        };
460        resp.write_u32(actual);
461    }
462
463    fn process_swo_control(&mut self, mut req: Request, resp: &mut ResponseWriter) {
464        let swo = if let Some(swo) = &mut self.swo {
465            swo
466        } else {
467            resp.write_err();
468            return;
469        };
470
471        match swo::SwoControl::try_from(req.next_u8()) {
472            Ok(control) => {
473                swo.set_control(control);
474                resp.write_ok();
475            }
476            _ => resp.write_err(),
477        }
478    }
479
480    fn process_swo_status(&mut self, _req: Request, resp: &mut ResponseWriter) {
481        // Trace status:
482        // Bit 0: trace capture active
483        // Bit 6: trace stream error (always written as 0)
484        // Bit 7: trace buffer overflow (always written as 0)
485        let (active, len) = if let Some(swo) = &self.swo {
486            (swo.is_active(), swo.bytes_available())
487        } else {
488            (false, 0)
489        };
490
491        resp.write_u8(active as u8);
492        // Trace count: remaining bytes in buffer
493        resp.write_u32(len);
494    }
495
496    fn process_swo_extended_status(&mut self, _req: Request, resp: &mut ResponseWriter) {
497        // Trace status:
498        // Bit 0: trace capture active
499        // Bit 6: trace stream error (always written as 0)
500        // Bit 7: trace buffer overflow (always written as 0)
501        let (active, len) = if let Some(swo) = &self.swo {
502            (swo.is_active(), swo.bytes_available())
503        } else {
504            (false, 0)
505        };
506        resp.write_u8(active as u8);
507        // Trace count: remaining bytes in buffer.
508        resp.write_u32(len);
509        // Index: sequence number of next trace. Always written as 0.
510        resp.write_u32(0);
511        // TD_TimeStamp: test domain timer value for trace sequence
512        resp.write_u32(0);
513    }
514
515    fn process_swo_data(&mut self, mut req: Request, resp: &mut ResponseWriter) {
516        let active = if let Some(swo) = &mut self.swo {
517            swo.is_active()
518        } else {
519            false
520        };
521
522        // Write status byte to response
523        resp.write_u8(active as u8);
524
525        // Skip length for now
526        resp.skip(2);
527
528        let mut buf = resp.remaining();
529
530        // Limit maximum return size to maximum requested bytes
531        let n = req.next_u16() as usize;
532        if buf.len() > n {
533            buf = &mut buf[..n];
534        }
535
536        // Read data from UART
537        let len = if let Some(swo) = &mut self.swo {
538            swo.polling_data(&mut buf)
539        } else {
540            0
541        };
542        resp.skip(len as _);
543
544        // Go back and write length
545        resp.write_u16_at(2, len as u16);
546    }
547
548    fn process_jtag_sequence(&mut self, req: Request, resp: &mut ResponseWriter) {
549        self.state.to_jtag();
550
551        match &mut self.state {
552            State::Jtag(jtag) => {
553                // Run requested JTAG sequences. Cannot fail.
554                let size = jtag.sequences(req.rest(), resp.remaining());
555                resp.skip(size as _);
556
557                resp.write_ok();
558            }
559            _ => resp.write_err(),
560        };
561    }
562
563    fn process_jtag_configure(&self, _req: Request, _resp: &mut ResponseWriter) {
564        // TODO: Implement one day (needs proper JTAG support)
565    }
566
567    fn process_jtag_idcode(&self, _req: Request, _resp: &mut ResponseWriter) {
568        // TODO: Implement one day (needs proper JTAG support)
569    }
570
571    fn process_transfer_configure(&mut self, mut req: Request, resp: &mut ResponseWriter) {
572        // We don't support variable idle cycles
573        // TODO: Should we?
574        let _idle_cycles = req.next_u8();
575
576        // Send number of wait retries through to SWD
577        self.swd_wait_retries = req.next_u16() as usize;
578
579        // Store number of match retries
580        self.match_retries = req.next_u16() as usize;
581
582        resp.write_ok();
583    }
584
585    fn process_transfer(&mut self, mut req: Request, resp: &mut ResponseWriter) {
586        self.state.to_last_mode();
587
588        let _idx = req.next_u8();
589        let ntransfers = req.next_u8();
590        let mut match_mask = 0xFFFF_FFFFu32;
591
592        match &mut self.state {
593            State::Jtag(_jtag) => {
594                // TODO: Implement one day.
595            }
596            State::Swd(swd) => {
597                // Skip two bytes in resp to reserve space for final status,
598                // which we update while processing.
599                resp.write_u16(0);
600
601                for transfer_idx in 0..ntransfers {
602                    // Store how many transfers we execute in the response
603                    resp.write_u8_at(1, transfer_idx + 1);
604
605                    // Parse the next transfer request
606                    let transfer_req = req.next_u8();
607                    let apndp = swd::APnDP::try_from(transfer_req & (1 << 0)).unwrap();
608                    let rnw = swd::RnW::try_from((transfer_req & (1 << 1)) >> 1).unwrap();
609                    let a = swd::DPRegister::try_from((transfer_req & (3 << 2)) >> 2).unwrap();
610                    let vmatch = (transfer_req & (1 << 4)) != 0;
611                    let mmask = (transfer_req & (1 << 5)) != 0;
612                    let _ts = (transfer_req & (1 << 7)) != 0;
613
614                    if rnw == swd::RnW::R {
615                        // Issue register read
616                        let mut read_value = if apndp == swd::APnDP::AP {
617                            // Reads from AP are posted, so we issue the
618                            // read and subsequently read RDBUFF for the data.
619                            // This requires an additional transfer so we'd
620                            // ideally keep track of posted reads and just
621                            // keep issuing new AP reads, but our reads are
622                            // sufficiently fast that for now this is simpler.
623                            let rdbuff = swd::DPRegister::RDBUFF;
624                            if swd
625                                .read_ap(self.swd_wait_retries, a)
626                                .check(resp.mut_at(2))
627                                .is_none()
628                            {
629                                break;
630                            }
631                            match swd
632                                .read_dp(self.swd_wait_retries, rdbuff)
633                                .check(resp.mut_at(2))
634                            {
635                                Some(v) => v,
636                                None => break,
637                            }
638                        } else {
639                            // Reads from DP are not posted, so directly read the register.
640                            match swd.read_dp(self.swd_wait_retries, a).check(resp.mut_at(2)) {
641                                Some(v) => v,
642                                None => break,
643                            }
644                        };
645
646                        // Handle value match requests by retrying if needed.
647                        // Since we're re-reading the same register the posting
648                        // is less important and we can just use the returned value.
649                        if vmatch {
650                            let target_value = req.next_u32();
651                            let mut match_tries = 0;
652                            while (read_value & match_mask) != target_value {
653                                match_tries += 1;
654                                if match_tries > self.match_retries {
655                                    break;
656                                }
657
658                                read_value = match swd
659                                    .read(self.swd_wait_retries, apndp.into(), a)
660                                    .check(resp.mut_at(2))
661                                {
662                                    Some(v) => v,
663                                    None => break,
664                                }
665                            }
666
667                            // If we didn't read the correct value, set the value mismatch
668                            // flag in the response and quit early.
669                            if (read_value & match_mask) != target_value {
670                                resp.write_u8_at(1, resp.read_u8_at(1) | (1 << 4));
671                                break;
672                            }
673                        } else {
674                            // Save read register value
675                            resp.write_u32(read_value);
676                        }
677                    } else {
678                        // Write transfer processing
679
680                        // Writes with match_mask set just update the match mask
681                        if mmask {
682                            match_mask = req.next_u32();
683                            continue;
684                        }
685
686                        // Otherwise issue register write
687                        let write_value = req.next_u32();
688                        if swd
689                            .write(self.swd_wait_retries, apndp, a, write_value)
690                            .check(resp.mut_at(2))
691                            .is_none()
692                        {
693                            break;
694                        }
695                    }
696                }
697            }
698            _ => return,
699        }
700    }
701
702    fn process_transfer_block(&mut self, mut req: Request, resp: &mut ResponseWriter) {
703        self.state.to_last_mode();
704
705        let _idx = req.next_u8();
706        let ntransfers = req.next_u16();
707        let transfer_req = req.next_u8();
708        let apndp = swd::APnDP::try_from(transfer_req & (1 << 0)).unwrap();
709        let rnw = swd::RnW::try_from((transfer_req & (1 << 1)) >> 1).unwrap();
710        let a = swd::DPRegister::try_from((transfer_req & (3 << 2)) >> 2).unwrap();
711
712        match &mut self.state {
713            State::Jtag(_jtag) => {
714                // TODO: Implement one day.
715            }
716            State::Swd(swd) => {
717                // Skip three bytes in resp to reserve space for final status,
718                // which we update while processing.
719                resp.write_u16(0);
720                resp.write_u8(0);
721
722                // Keep track of how many transfers we executed,
723                // so if there is an error the host knows where
724                // it happened.
725                let mut transfers = 0;
726
727                // If reading an AP register, post first read early.
728                if rnw == swd::RnW::R
729                    && apndp == swd::APnDP::AP
730                    && swd
731                        .read_ap(self.swd_wait_retries, a)
732                        .check(resp.mut_at(3))
733                        .is_none()
734                {
735                    // Quit early on error
736                    resp.write_u16_at(1, 1);
737                    return;
738                }
739
740                for transfer_idx in 0..ntransfers {
741                    transfers = transfer_idx;
742                    if rnw == swd::RnW::R {
743                        // Handle repeated reads
744                        let read_value = if apndp == swd::APnDP::AP {
745                            // For AP reads, the first read was posted, so on the final
746                            // read we need to read RDBUFF instead of the AP register.
747                            if transfer_idx < ntransfers - 1 {
748                                match swd.read_ap(self.swd_wait_retries, a).check(resp.mut_at(3)) {
749                                    Some(v) => v,
750                                    None => break,
751                                }
752                            } else {
753                                let rdbuff = swd::DPRegister::RDBUFF.into();
754                                match swd
755                                    .read_dp(self.swd_wait_retries, rdbuff)
756                                    .check(resp.mut_at(3))
757                                {
758                                    Some(v) => v,
759                                    None => break,
760                                }
761                            }
762                        } else {
763                            // For DP reads, no special care required
764                            match swd.read_dp(self.swd_wait_retries, a).check(resp.mut_at(3)) {
765                                Some(v) => v,
766                                None => break,
767                            }
768                        };
769
770                        // Save read register value to response
771                        resp.write_u32(read_value);
772                    } else {
773                        // Handle repeated register writes
774                        let write_value = req.next_u32();
775                        let result = swd.write(self.swd_wait_retries, apndp, a, write_value);
776                        if result.check(resp.mut_at(3)).is_none() {
777                            break;
778                        }
779                    }
780                }
781
782                // Write number of transfers to response
783                resp.write_u16_at(1, transfers + 1);
784            }
785            _ => return,
786        }
787    }
788
789    fn process_transfer_abort(&mut self) {
790        // We'll only ever receive an abort request when we're not already
791        // processing anything else, since processing blocks checking for
792        // new requests. Therefore there's nothing to do here.
793    }
794
795    fn process_execute_commands(&self, _req: Request, _resp: &mut ResponseWriter) {
796        // TODO: Implement one day.
797    }
798
799    fn process_queue_commands(&self, _req: Request, _resp: &mut ResponseWriter) {
800        // TODO: Implement one day.
801    }
802}
803
804trait CheckResult<T> {
805    /// Check result of an SWD transfer, updating the response status byte.
806    ///
807    /// Returns Some(T) on successful transfer, None on error.
808    fn check(self, resp: &mut u8) -> Option<T>;
809}
810
811impl<T> CheckResult<T> for swd::Result<T> {
812    fn check(self, resp: &mut u8) -> Option<T> {
813        match self {
814            Ok(v) => {
815                *resp = 1;
816                Some(v)
817            }
818            Err(swd::Error::AckWait) => {
819                *resp = 2;
820                None
821            }
822            Err(swd::Error::AckFault) => {
823                *resp = 4;
824                None
825            }
826            Err(_) => {
827                *resp = (1 << 3) | 7;
828                None
829            }
830        }
831    }
832}
833
834#[cfg(test)]
835mod test {
836    use super::*;
837    use crate::mock_device::*;
838    use mockall::predicate::*;
839
840    struct FakeLEDs {}
841    impl DapLeds for FakeLEDs {
842        fn react_to_host_status(&mut self, _host_status: HostStatus) {}
843    }
844
845    struct StdDelayUs {}
846    impl DelayNs for StdDelayUs {
847        fn delay_ns(&mut self, ns: u32) {
848            std::thread::sleep(std::time::Duration::from_nanos(ns as u64));
849        }
850    }
851
852    type TestDap<'a> = Dap<
853        'a,
854        MockSwdJtagDevice,
855        FakeLEDs,
856        StdDelayUs,
857        MockSwdJtagDevice,
858        MockSwdJtagDevice,
859        swo::MockSwo,
860    >;
861
862    #[test]
863    fn test_swd_output_reset() {
864        let mut dap = TestDap::new(
865            MockSwdJtagDevice::new(),
866            FakeLEDs {},
867            StdDelayUs {},
868            None,
869            "test_dap",
870        );
871
872        let report = [0x1Du8, 1, 52, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0];
873        let mut rbuf = [0u8; 64];
874        dap.state.to_swd();
875        match &mut dap.state {
876            State::Swd(swd) => {
877                swd.expect_write_sequence()
878                    .once()
879                    .with(eq(52), eq([0xFFu8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0]))
880                    .return_const(Ok(()));
881            }
882            _ => assert!(false, "can't switch to swd"),
883        }
884        let rsize = dap.process_command(&report, &mut rbuf, DapVersion::V2);
885        assert_eq!(rsize, 2);
886        assert_eq!(&rbuf[..2], &[0x1Du8, 0x00])
887    }
888
889    #[test]
890    fn test_swd_output_max_size() {
891        let mut dap = TestDap::new(
892            MockSwdJtagDevice::new(),
893            FakeLEDs {},
894            StdDelayUs {},
895            None,
896            "test_dap",
897        );
898
899        let report = [0x1Du8, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00];
900        let mut rbuf = [0u8; 64];
901        dap.state.to_swd();
902        match &mut dap.state {
903            State::Swd(swd) => {
904                swd.expect_write_sequence()
905                    .once()
906                    .with(
907                        eq(64),
908                        eq([0xFFu8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00]),
909                    )
910                    .return_const(Ok(()));
911            }
912            _ => assert!(false, "can't switch to swd"),
913        }
914        let rsize = dap.process_command(&report, &mut rbuf, DapVersion::V2);
915        assert_eq!(rsize, 2);
916        assert_eq!(&rbuf[..2], &[0x1Du8, 0x00])
917    }
918
919    #[test]
920    fn test_swd_input() {
921        let mut dap = TestDap::new(
922            MockSwdJtagDevice::new(),
923            FakeLEDs {},
924            StdDelayUs {},
925            None,
926            "test_dap",
927        );
928
929        let report = [0x1Du8, 1, 0x80 | 52];
930        let mut rbuf = [0u8; 64];
931        dap.state.to_swd();
932        match &mut dap.state {
933            State::Swd(swd) => {
934                swd.expect_read_sequence()
935                    .once()
936                    .withf(|nbits, buf| buf.len() >= 7 && *nbits == 52)
937                    .returning(|_, buf| {
938                        buf[..7].clone_from_slice(&[0xFFu8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0]);
939                        Ok(())
940                    });
941            }
942            _ => assert!(false, "can't switch to swd"),
943        }
944        let rsize = dap.process_command(&report, &mut rbuf, DapVersion::V2);
945        assert_eq!(rsize, 9);
946        assert_eq!(
947            &rbuf[..9],
948            &[0x1Du8, 0x00, 0xFFu8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0]
949        )
950    }
951
952    #[test]
953    fn test_swd_input_max_size() {
954        let mut dap = TestDap::new(
955            MockSwdJtagDevice::new(),
956            FakeLEDs {},
957            StdDelayUs {},
958            None,
959            "test_dap",
960        );
961
962        let report = [0x1Du8, 1, 0x80];
963        let mut rbuf = [0u8; 64];
964        dap.state.to_swd();
965        match &mut dap.state {
966            State::Swd(swd) => {
967                swd.expect_read_sequence()
968                    .once()
969                    .withf(|nbits, buf| buf.len() >= 8 && *nbits == 64)
970                    .returning(|_, buf| {
971                        buf[..8]
972                            .clone_from_slice(&[0xFFu8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00]);
973                        Ok(())
974                    });
975            }
976            _ => assert!(false, "can't switch to swd"),
977        }
978        let rsize = dap.process_command(&report, &mut rbuf, DapVersion::V2);
979        assert_eq!(rsize, 10);
980        assert_eq!(
981            &rbuf[..10],
982            &[0x1Du8, 0x00, 0xFFu8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00]
983        )
984    }
985
986    #[test]
987    fn test_target_select() {
988        let mut dap = TestDap::new(
989            MockSwdJtagDevice::new(),
990            FakeLEDs {},
991            StdDelayUs {},
992            None,
993            "test_dap",
994        );
995
996        // write 8 bits, read 5 bits, write 33 bits
997        let report = [0x1Du8, 3, 8, 0b10111101, 0x80 | 5, 33, 0x56, 0x83, 0xAB, 0x32, 0x01];
998        let mut rbuf = [0u8; 64];
999        dap.state.to_swd();
1000        match &mut dap.state {
1001            State::Swd(swd) => {
1002                swd.expect_write_sequence()
1003                    .once()
1004                    .with(
1005                        eq(8),
1006                        eq([0b10111101u8]),
1007                    )
1008                    .return_const(Ok(()));
1009                swd.expect_read_sequence()
1010                    .once()
1011                    .withf(|nbits, buf| buf.len() >= 1 && *nbits == 5)
1012                    .returning(|_, buf| {
1013                        buf[0] = 0x1F;
1014                        Ok(())
1015                    });
1016                swd.expect_write_sequence()
1017                    .once()
1018                    .with(
1019                        eq(33),
1020                        eq([0x56, 0x83, 0xAB, 0x32, 0x01]),
1021                    )
1022                    .return_const(Ok(()));
1023            }
1024            _ => assert!(false, "can't switch to swd"),
1025        }
1026        let rsize = dap.process_command(&report, &mut rbuf, DapVersion::V2);
1027        assert_eq!(rsize, 3);
1028        assert_eq!(
1029            &rbuf[..3],
1030            &[0x1Du8, 0x00, 0x1F]
1031        )
1032    }
1033}