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
16pub trait DapLeds {
18 fn react_to_host_status(&mut self, host_status: HostStatus);
20}
21
22pub 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 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 pub fn new(
46 dependencies: DEPS,
47 leds: LEDS,
48 wait: WAIT,
49 swo: Option<SWO>,
50 version_string: &'a str,
51 ) -> Self {
52 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 leds,
64 wait,
65 }
66 }
67
68 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 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 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 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 Ok(DapInfoID::VendorID) => resp.write_u8(0),
141 Ok(DapInfoID::ProductID) => resp.write_u8(0),
142 Ok(DapInfoID::SerialNumber) => resp.write_u8(0),
143 Ok(DapInfoID::FirmwareVersion) => {
145 resp.write_u8(self.version_string.len() as u8);
146 resp.write_slice(self.version_string.as_bytes());
147 }
148 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 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 resp.write_u8(1);
186 }
187 Ok(DapInfoID::MaxPacketSize) => {
188 resp.write_u8(2);
189 match version {
190 DapVersion::V1 => {
191 resp.write_u16(usb::DAP1_PACKET_SIZE);
193 }
194 DapVersion::V2 => {
195 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 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 match (SWD::AVAILABLE, JTAG::AVAILABLE, port) {
238 (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 (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 (true, false, ConnectPort::JTAG) | (false, true, ConnectPort::SWD) => {
257 resp.write_u8(ConnectPortResponse::Failed as u8);
258 }
259
260 (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 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 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); 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 0 => 256,
341 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 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(); let sequence_count = req.next_u8();
389 let success = (0..sequence_count).map(|_| {
390 let sequence_info = req.next_u8();
392 let nbits: usize = match sequence_info & 0x3F {
393 0 => 64,
395 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 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 resp.write_u32(len);
494 }
495
496 fn process_swo_extended_status(&mut self, _req: Request, resp: &mut ResponseWriter) {
497 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 resp.write_u32(len);
509 resp.write_u32(0);
511 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 resp.write_u8(active as u8);
524
525 resp.skip(2);
527
528 let mut buf = resp.remaining();
529
530 let n = req.next_u16() as usize;
532 if buf.len() > n {
533 buf = &mut buf[..n];
534 }
535
536 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 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 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 }
566
567 fn process_jtag_idcode(&self, _req: Request, _resp: &mut ResponseWriter) {
568 }
570
571 fn process_transfer_configure(&mut self, mut req: Request, resp: &mut ResponseWriter) {
572 let _idle_cycles = req.next_u8();
575
576 self.swd_wait_retries = req.next_u16() as usize;
578
579 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 }
596 State::Swd(swd) => {
597 resp.write_u16(0);
600
601 for transfer_idx in 0..ntransfers {
602 resp.write_u8_at(1, transfer_idx + 1);
604
605 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 let mut read_value = if apndp == swd::APnDP::AP {
617 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 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 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 (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 resp.write_u32(read_value);
676 }
677 } else {
678 if mmask {
682 match_mask = req.next_u32();
683 continue;
684 }
685
686 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 }
716 State::Swd(swd) => {
717 resp.write_u16(0);
720 resp.write_u8(0);
721
722 let mut transfers = 0;
726
727 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 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 let read_value = if apndp == swd::APnDP::AP {
745 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 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 resp.write_u32(read_value);
772 } else {
773 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 resp.write_u16_at(1, transfers + 1);
784 }
785 _ => return,
786 }
787 }
788
789 fn process_transfer_abort(&mut self) {
790 }
794
795 fn process_execute_commands(&self, _req: Request, _resp: &mut ResponseWriter) {
796 }
798
799 fn process_queue_commands(&self, _req: Request, _resp: &mut ResponseWriter) {
800 }
802}
803
804trait CheckResult<T> {
805 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 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}