probe_rs/
probe.rs

1//! Probe drivers
2pub(crate) mod common;
3pub(crate) mod usb_util;
4
5pub mod blackmagic;
6pub mod ch347usbjtag;
7pub mod cmsisdap;
8pub mod espusbjtag;
9pub mod fake_probe;
10pub mod ftdi;
11pub mod glasgow;
12pub mod jlink;
13pub mod list;
14pub mod sifliuart;
15pub mod stlink;
16pub mod wlink;
17
18use crate::architecture::arm::sequences::{ArmDebugSequence, DefaultArmSequence};
19use crate::architecture::arm::{ArmDebugInterface, ArmError, DapError};
20use crate::architecture::arm::{RegisterAddress, SwoAccess, communication_interface::DapProbe};
21use crate::architecture::riscv::communication_interface::{RiscvError, RiscvInterfaceBuilder};
22use crate::architecture::xtensa::communication_interface::{
23    XtensaCommunicationInterface, XtensaDebugInterfaceState, XtensaError,
24};
25use crate::config::TargetSelector;
26use crate::config::registry::Registry;
27use crate::probe::common::JtagState;
28use crate::{Error, Permissions, Session};
29use bitvec::slice::BitSlice;
30use bitvec::vec::BitVec;
31use common::ScanChainError;
32use nusb::DeviceInfo;
33use probe_rs_target::ScanChainElement;
34use serde::{Deserialize, Deserializer, Serialize, Serializer};
35use std::any::Any;
36use std::collections::HashMap;
37use std::fmt;
38use std::sync::Arc;
39
40/// Used to log warnings when the measured target voltage is
41/// lower than 1.4V, if at all measurable.
42const LOW_TARGET_VOLTAGE_WARNING_THRESHOLD: f32 = 1.4;
43
44/// The protocol that is to be used by the probe when communicating with the target.
45///
46/// For ARM select `Swd` or `Jtag`, for RISC-V select `Jtag`.
47#[derive(Copy, Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)]
48pub enum WireProtocol {
49    /// Serial Wire Debug is ARMs proprietary standard for communicating with ARM cores.
50    /// You can find specifics in the [`ARM Debug Interface v5.2`](https://developer.arm.com/documentation/ihi0031/f/?lang=en) specification.
51    Swd,
52    /// JTAG is a standard which is supported by many chips independent of architecture.
53    /// See [`Wikipedia`](https://en.wikipedia.org/wiki/JTAG) for more info.
54    Jtag,
55}
56
57impl fmt::Display for WireProtocol {
58    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59        match self {
60            WireProtocol::Swd => f.write_str("SWD"),
61            WireProtocol::Jtag => f.write_str("JTAG"),
62        }
63    }
64}
65
66impl std::str::FromStr for WireProtocol {
67    type Err = String;
68
69    fn from_str(s: &str) -> Result<Self, Self::Err> {
70        match &s.to_ascii_lowercase()[..] {
71            "swd" => Ok(WireProtocol::Swd),
72            "jtag" => Ok(WireProtocol::Jtag),
73            _ => Err(format!(
74                "'{s}' is not a valid protocol. Choose either 'swd' or 'jtag'."
75            )),
76        }
77    }
78}
79
80/// A command queued in a batch for later execution
81///
82/// Mostly used internally but returned in DebugProbeError to indicate
83/// which batched command actually encountered the error.
84#[derive(Clone, Debug)]
85pub enum BatchCommand {
86    /// Read from a port
87    Read(RegisterAddress),
88
89    /// Write to a port
90    Write(RegisterAddress, u32),
91}
92
93impl fmt::Display for BatchCommand {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        match self {
96            BatchCommand::Read(port) => {
97                write!(f, "Read(port={port:?})")
98            }
99            BatchCommand::Write(port, data) => {
100                write!(f, "Write(port={port:?}, data={data:#010x})")
101            }
102        }
103    }
104}
105
106/// Marker trait for all probe errors.
107pub trait ProbeError: std::error::Error + Send + Sync + std::any::Any {}
108
109impl std::error::Error for Box<dyn ProbeError> {
110    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
111        self.as_ref().source()
112    }
113}
114
115/// A probe-specific error.
116#[derive(Debug, thiserror::Error)]
117#[error(transparent)]
118pub struct BoxedProbeError(#[from] Box<dyn ProbeError>);
119
120impl BoxedProbeError {
121    fn as_any(&self) -> &dyn std::any::Any {
122        self.0.as_ref()
123    }
124
125    /// Returns true if the underlying error is of type `T`.
126    pub fn is<T: ProbeError>(&self) -> bool {
127        self.as_any().is::<T>()
128    }
129
130    /// Attempts to downcast the error to a specific error type.
131    pub fn downcast_ref<T: ProbeError>(&self) -> Option<&T> {
132        self.as_any().downcast_ref()
133    }
134
135    /// Attempts to downcast the error to a specific error type.
136    pub fn downcast_mut<T: ProbeError>(&mut self) -> Option<&mut T> {
137        let any: &mut dyn std::any::Any = self.0.as_mut();
138        any.downcast_mut()
139    }
140}
141
142impl<T> From<T> for BoxedProbeError
143where
144    T: ProbeError,
145{
146    fn from(e: T) -> Self {
147        BoxedProbeError(Box::new(e))
148    }
149}
150
151/// This error occurs whenever the debug probe logic encounters an error while operating the relevant debug probe.
152#[derive(thiserror::Error, Debug, docsplay::Display)]
153pub enum DebugProbeError {
154    /// USB Communication Error
155    Usb(#[source] std::io::Error),
156
157    /// An error which is specific to the debug probe in use occurred.
158    ProbeSpecific(#[source] BoxedProbeError),
159
160    /// The debug probe could not be created.
161    ProbeCouldNotBeCreated(#[from] ProbeCreationError),
162
163    /// The probe does not support the {0} protocol.
164    UnsupportedProtocol(WireProtocol),
165
166    /// The selected probe does not support the '{interface_name}' interface.
167    ///
168    /// This happens if a probe does not support certain functionality, such as:
169    /// - ARM debugging
170    /// - RISC-V debugging
171    /// - SWO
172    #[ignore_extra_doc_attributes]
173    InterfaceNotAvailable {
174        /// The name of the unsupported interface.
175        interface_name: &'static str,
176    },
177
178    /// The probe does not support the requested speed setting ({0} kHz).
179    UnsupportedSpeed(u32),
180
181    /// You need to be attached to the target to perform this action.
182    ///
183    /// The debug probe did not yet perform the init sequence.
184    /// Try calling [`DebugProbe::attach`] before trying again.
185    #[ignore_extra_doc_attributes]
186    NotAttached,
187
188    /// You need to be detached from the target to perform this action.
189    ///
190    /// The debug probe already performed the init sequence.
191    /// Try running the failing command before [`DebugProbe::attach`].
192    #[ignore_extra_doc_attributes]
193    Attached,
194
195    /// Failed to find or attach to the target. Please check the wiring before retrying.
196    TargetNotFound,
197
198    /// Error in previous batched command.
199    BatchError(BatchCommand),
200
201    /// The '{function_name}' functionality is not implemented yet.
202    ///
203    /// The variant of the function you called is not yet implemented.
204    /// This can happen if some debug probe has some unimplemented functionality for a specific protocol or architecture.
205    #[ignore_extra_doc_attributes]
206    NotImplemented {
207        /// The name of the unsupported functionality.
208        function_name: &'static str,
209    },
210
211    /// The '{command_name}' functionality is not supported by the selected probe.
212    /// This can happen when a probe does not allow for setting speed manually for example.
213    CommandNotSupportedByProbe {
214        /// The name of the unsupported command.
215        command_name: &'static str,
216    },
217
218    /// An error occurred handling the JTAG scan chain.
219    JtagScanChain(#[from] ScanChainError),
220
221    /// Some other error occurred
222    #[display("{0}")]
223    Other(String),
224
225    /// A timeout occurred during probe operation.
226    Timeout,
227}
228
229impl<T: ProbeError> From<T> for DebugProbeError {
230    fn from(e: T) -> Self {
231        Self::ProbeSpecific(BoxedProbeError::from(e))
232    }
233}
234
235/// An error during probe creation occurred.
236/// This is almost always a sign of a bad USB setup.
237/// Check UDEV rules if you are on Linux and try installing Zadig
238/// (This will disable vendor specific drivers for your probe!) if you are on Windows.
239#[derive(thiserror::Error, Debug, docsplay::Display)]
240pub enum ProbeCreationError {
241    /// The selected debug probe was not found.
242    /// This can be due to permissions.
243    NotFound,
244
245    /// The selected USB device could not be opened.
246    CouldNotOpen,
247
248    /// An HID API occurred.
249    #[cfg(feature = "cmsisdap_v1")]
250    HidApi(#[from] hidapi::HidError),
251
252    /// A USB error occurred.
253    Usb(#[source] std::io::Error),
254
255    /// An error specific with the selected probe occurred.
256    ProbeSpecific(#[source] BoxedProbeError),
257
258    /// Something else happened.
259    #[display("{0}")]
260    Other(&'static str),
261}
262
263impl<T: ProbeError> From<T> for ProbeCreationError {
264    fn from(e: T) -> Self {
265        Self::ProbeSpecific(BoxedProbeError::from(e))
266    }
267}
268
269/// The Probe struct is a generic wrapper over the different
270/// probes supported.
271///
272/// # Examples
273///
274/// ## Open the first probe found
275///
276/// The `list_all` and `from_probe_info` functions can be used
277/// to create a new `Probe`:
278///
279/// ```no_run
280/// use probe_rs::probe::{Probe, list::Lister};
281///
282/// let lister = Lister::new();
283///
284/// let probe_list = lister.list_all();
285/// let probe = probe_list[0].open();
286/// ```
287#[derive(Debug)]
288pub struct Probe {
289    inner: Box<dyn DebugProbe>,
290    attached: bool,
291}
292
293impl Probe {
294    /// Create a new probe from a more specific probe driver.
295    pub fn new(probe: impl DebugProbe + 'static) -> Self {
296        Self {
297            inner: Box::new(probe),
298            attached: false,
299        }
300    }
301
302    pub(crate) fn from_attached_probe(probe: Box<dyn DebugProbe>) -> Self {
303        Self {
304            inner: probe,
305            attached: true,
306        }
307    }
308
309    /// Same as [`Probe::new`] but without automatic boxing in case you already have a box.
310    pub fn from_specific_probe(probe: Box<dyn DebugProbe>) -> Self {
311        Probe {
312            inner: probe,
313            attached: false,
314        }
315    }
316
317    /// Get the human readable name for the probe.
318    pub fn get_name(&self) -> String {
319        self.inner.get_name().to_string()
320    }
321
322    /// Attach to the chip.
323    ///
324    /// This runs all the necessary protocol init routines.
325    ///
326    /// The target is loaded from the builtin list of targets.
327    /// If this doesn't work, you might want to try [`Probe::attach_under_reset`].
328    pub fn attach(
329        self,
330        target: impl Into<TargetSelector>,
331        permissions: Permissions,
332    ) -> Result<Session, Error> {
333        let registry = Registry::from_builtin_families();
334        self.attach_with_registry(target, permissions, &registry)
335    }
336
337    /// Attach to the chip.
338    ///
339    /// This runs all the necessary protocol init routines.
340    ///
341    /// The target is loaded from a custom registry.
342    /// If this doesn't work, you might want to try [`Probe::attach_under_reset`].
343    pub fn attach_with_registry(
344        self,
345        target: impl Into<TargetSelector>,
346        permissions: Permissions,
347        registry: &Registry,
348    ) -> Result<Session, Error> {
349        Session::new(
350            self,
351            target.into(),
352            AttachMethod::Normal,
353            permissions,
354            registry,
355        )
356    }
357
358    /// Attach to a target without knowing what target you have at hand.
359    /// This can be used for automatic device discovery or performing operations on an unspecified target.
360    pub fn attach_to_unspecified(&mut self) -> Result<(), Error> {
361        self.inner.attach()?;
362        self.attached = true;
363        Ok(())
364    }
365
366    /// A combination of [`Probe::attach_to_unspecified`] and [`Probe::attach_under_reset`].
367    pub fn attach_to_unspecified_under_reset(&mut self) -> Result<(), Error> {
368        if let Some(dap_probe) = self.try_as_dap_probe() {
369            DefaultArmSequence(()).reset_hardware_assert(dap_probe)?;
370        } else {
371            tracing::info!(
372                "Custom reset sequences are not supported on {}.",
373                self.get_name()
374            );
375            tracing::info!("Falling back to standard probe reset.");
376            self.target_reset_assert()?;
377        }
378        self.attach_to_unspecified()?;
379        Ok(())
380    }
381
382    /// Attach to the chip under hard-reset.
383    ///
384    /// This asserts the reset pin via the probe, plays the protocol init routines and deasserts the pin.
385    /// This is necessary if the chip is not responding to the SWD reset sequence.
386    /// For example this can happen if the chip has the SWDIO pin remapped.
387    ///
388    /// The target is loaded from the builtin list of targets.
389    pub fn attach_under_reset(
390        self,
391        target: impl Into<TargetSelector>,
392        permissions: Permissions,
393    ) -> Result<Session, Error> {
394        let registry = Registry::from_builtin_families();
395        self.attach_under_reset_with_registry(target, permissions, &registry)
396    }
397
398    /// Attach to the chip under hard-reset.
399    ///
400    /// This asserts the reset pin via the probe, plays the protocol init routines and deasserts the pin.
401    /// This is necessary if the chip is not responding to the SWD reset sequence.
402    /// For example this can happen if the chip has the SWDIO pin remapped.
403    ///
404    /// The target is loaded from a custom registry.
405    pub fn attach_under_reset_with_registry(
406        self,
407        target: impl Into<TargetSelector>,
408        permissions: Permissions,
409        registry: &Registry,
410    ) -> Result<Session, Error> {
411        // The session will de-assert reset after connecting to the debug interface.
412        Session::new(
413            self,
414            target.into(),
415            AttachMethod::UnderReset,
416            permissions,
417            registry,
418        )
419        .map_err(|e| match e {
420            Error::Arm(ArmError::Timeout)
421            | Error::Riscv(RiscvError::Timeout)
422            | Error::Xtensa(XtensaError::Timeout) => Error::Other(
423                "Timeout while attaching to target under reset. \
424                    This can happen if the target is not responding to the reset sequence. \
425                    Ensure the chip's reset pin is connected, or try attaching without reset \
426                    (`connectUnderReset = false` for DAP Clients, or remove `connect-under-reset` \
427                        option from CLI options.)."
428                    .to_string(),
429            ),
430            e => e,
431        })
432    }
433
434    /// Selects the transport protocol to be used by the debug probe.
435    pub fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError> {
436        if !self.attached {
437            self.inner.select_protocol(protocol)
438        } else {
439            Err(DebugProbeError::Attached)
440        }
441    }
442
443    /// Get the currently selected protocol
444    ///
445    /// Depending on the probe, this might not be available.
446    pub fn protocol(&self) -> Option<WireProtocol> {
447        self.inner.active_protocol()
448    }
449
450    /// Leave debug mode
451    pub fn detach(&mut self) -> Result<(), crate::Error> {
452        self.attached = false;
453        self.inner.detach()?;
454        Ok(())
455    }
456
457    /// Resets the target device.
458    pub fn target_reset(&mut self) -> Result<(), DebugProbeError> {
459        self.inner.target_reset()
460    }
461
462    /// Asserts the reset of the target.
463    /// This is always the hard reset which means the reset wire has to be connected to work.
464    ///
465    /// This is not supported on all probes.
466    pub fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
467        tracing::debug!("Asserting target reset");
468        self.inner.target_reset_assert()
469    }
470
471    /// Deasserts the reset of the target.
472    /// This is always the hard reset which means the reset wire has to be connected to work.
473    ///
474    /// This is not supported on all probes.
475    pub fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
476        tracing::debug!("Deasserting target reset");
477        self.inner.target_reset_deassert()
478    }
479
480    /// Configure protocol speed to use in kHz
481    pub fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError> {
482        if !self.attached {
483            self.inner.set_speed(speed_khz)
484        } else {
485            Err(DebugProbeError::Attached)
486        }
487    }
488
489    /// Get the currently used maximum speed for the debug protocol in kHz.
490    ///
491    /// Not all probes report which speed is used, meaning this value is not
492    /// always the actual speed used. However, the speed should not be any
493    /// higher than this value.
494    pub fn speed_khz(&self) -> u32 {
495        self.inner.speed_khz()
496    }
497
498    /// Check if the probe has an interface to
499    /// debug Xtensa chips.
500    pub fn has_xtensa_interface(&self) -> bool {
501        self.inner.has_xtensa_interface()
502    }
503
504    /// Try to get a [`XtensaCommunicationInterface`], which can
505    /// can be used to communicate with chips using the Xtensa
506    /// architecture.
507    ///
508    /// The user is responsible for creating and managing the [`XtensaDebugInterfaceState`] state
509    /// object.
510    ///
511    /// If an error occurs while trying to connect, the probe is returned.
512    pub fn try_get_xtensa_interface<'probe>(
513        &'probe mut self,
514        state: &'probe mut XtensaDebugInterfaceState,
515    ) -> Result<XtensaCommunicationInterface<'probe>, XtensaError> {
516        if !self.attached {
517            Err(DebugProbeError::NotAttached.into())
518        } else {
519            Ok(self.inner.try_get_xtensa_interface(state)?)
520        }
521    }
522
523    /// Checks if the probe supports connecting to chips
524    /// using the Arm Debug Interface.
525    pub fn has_arm_debug_interface(&self) -> bool {
526        self.inner.has_arm_interface()
527    }
528
529    /// Try to get a trait object implementing [`ArmDebugInterface`], which can
530    /// can be used to communicate with chips using the ARM debug interface.
531    ///
532    /// If an error occurs while trying to connect, the probe is returned.
533    pub fn try_into_arm_debug_interface<'probe>(
534        self,
535        sequence: Arc<dyn ArmDebugSequence>,
536    ) -> Result<Box<dyn ArmDebugInterface + 'probe>, (Self, ArmError)> {
537        if !self.attached {
538            Err((self, DebugProbeError::NotAttached.into()))
539        } else {
540            self.inner
541                .try_get_arm_debug_interface(sequence)
542                .map_err(|(probe, err)| (Probe::from_attached_probe(probe), err))
543        }
544    }
545
546    /// Check if the probe has an interface to debug RISC-V chips.
547    pub fn has_riscv_interface(&self) -> bool {
548        self.inner.has_riscv_interface()
549    }
550
551    /// Try to get a [`RiscvInterfaceBuilder`] object, which can be used to set up a communication
552    /// interface with chips using the RISC-V architecture.
553    ///
554    /// The returned object can be used to create the interface state, which is required to
555    /// attach to the RISC-V target. The user is responsible for managing this state object.
556    ///
557    /// If an error occurs while trying to connect, the probe is returned.
558    pub fn try_get_riscv_interface_builder<'probe>(
559        &'probe mut self,
560    ) -> Result<Box<dyn RiscvInterfaceBuilder<'probe> + 'probe>, RiscvError> {
561        if !self.attached {
562            Err(DebugProbeError::NotAttached.into())
563        } else {
564            self.inner.try_get_riscv_interface_builder()
565        }
566    }
567
568    /// Returns a [`JtagAccess`] from the debug probe, if implemented.
569    pub fn try_as_jtag_probe(&mut self) -> Option<&mut dyn JtagAccess> {
570        self.inner.try_as_jtag_probe()
571    }
572
573    /// Gets a SWO interface from the debug probe.
574    ///
575    /// This does not work on all probes.
576    pub fn get_swo_interface(&self) -> Option<&dyn SwoAccess> {
577        self.inner.get_swo_interface()
578    }
579
580    /// Gets a mutable SWO interface from the debug probe.
581    ///
582    /// This does not work on all probes.
583    pub fn get_swo_interface_mut(&mut self) -> Option<&mut dyn SwoAccess> {
584        self.inner.get_swo_interface_mut()
585    }
586
587    /// Gets a DAP interface from the debug probe.
588    ///
589    /// This does not work on all probes.
590    pub fn try_as_dap_probe(&mut self) -> Option<&mut dyn DapProbe> {
591        self.inner.try_as_dap_probe()
592    }
593
594    /// Try reading the target voltage of via the connected voltage pin.
595    ///
596    /// This does not work on all probes.
597    pub fn get_target_voltage(&mut self) -> Result<Option<f32>, DebugProbeError> {
598        self.inner.get_target_voltage()
599    }
600
601    /// Try to convert the probe into a concrete probe type.
602    pub fn try_into<P: DebugProbe>(&mut self) -> Option<&mut P> {
603        (self.inner.as_mut() as &mut dyn Any).downcast_mut::<P>()
604    }
605}
606
607/// An abstraction over a probe driver type.
608///
609/// This trait has to be implemented by ever debug probe driver.
610///
611/// The `std::fmt::Display` implementation will be used to display the probe in the list of available probes,
612/// and should return a human-readable name for the probe type.
613pub trait ProbeFactory: std::any::Any + std::fmt::Display + std::fmt::Debug + Sync {
614    /// Creates a new boxed [`DebugProbe`] from a given [`DebugProbeSelector`].
615    /// This will be called for all available debug drivers when discovering probes.
616    /// When opening, it will open the first probe which succeeds during this call.
617    fn open(&self, selector: &DebugProbeSelector) -> Result<Box<dyn DebugProbe>, DebugProbeError>;
618
619    /// Returns a list of all available debug probes of the current type.
620    fn list_probes(&self) -> Vec<DebugProbeInfo>;
621
622    /// Returns a list of probes that match the optional selector.
623    ///
624    /// If the selector is `None`, all available probes are returned.
625    fn list_probes_filtered(&self, selector: Option<&DebugProbeSelector>) -> Vec<DebugProbeInfo> {
626        // The default implementation falls back to listing all probes so that drivers don't need
627        // to deal with the common filtering logic.
628        self.list_probes()
629            .into_iter()
630            .filter(|probe| selector.as_ref().is_none_or(|s| s.matches_probe(probe)))
631            .collect()
632    }
633}
634
635/// An abstraction over a general debug probe.
636///
637/// This trait has to be implemented by ever debug probe driver.
638pub trait DebugProbe: Any + Send + fmt::Debug {
639    /// Get human readable name for the probe.
640    fn get_name(&self) -> &str;
641
642    /// Get the currently used maximum speed for the debug protocol in kHz.
643    ///
644    /// Not all probes report which speed is used, meaning this value is not
645    /// always the actual speed used. However, the speed should not be any
646    /// higher than this value.
647    fn speed_khz(&self) -> u32;
648
649    /// Set the speed in kHz used for communication with the target device.
650    ///
651    /// The desired speed might not be supported by the probe. If the desired
652    /// speed is not directly supported, a lower speed will be selected if possible.
653    ///
654    /// If possible, the actual speed used is returned by the function. Some probes
655    /// cannot report this, so the value may be inaccurate.
656    ///
657    /// If the requested speed is not supported,
658    /// `DebugProbeError::UnsupportedSpeed` will be returned.
659    ///
660    fn set_speed(&mut self, speed_khz: u32) -> Result<u32, DebugProbeError>;
661
662    /// Attach to the chip.
663    ///
664    /// This should run all the necessary protocol init routines.
665    fn attach(&mut self) -> Result<(), DebugProbeError>;
666
667    /// Detach from the chip.
668    ///
669    /// This should run all the necessary protocol deinit routines.
670    ///
671    /// If the probe uses batched commands, this will also cause all
672    /// remaining commands to be executed. If an error occurs during
673    /// this execution, the probe might remain in the attached state.
674    fn detach(&mut self) -> Result<(), crate::Error>;
675
676    /// This should hard reset the target device.
677    fn target_reset(&mut self) -> Result<(), DebugProbeError>;
678
679    /// This should assert the reset pin of the target via debug probe.
680    fn target_reset_assert(&mut self) -> Result<(), DebugProbeError>;
681
682    /// This should deassert the reset pin of the target via debug probe.
683    fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError>;
684
685    /// Selects the transport protocol to be used by the debug probe.
686    fn select_protocol(&mut self, protocol: WireProtocol) -> Result<(), DebugProbeError>;
687
688    /// Get the transport protocol currently in active use by the debug probe.
689    fn active_protocol(&self) -> Option<WireProtocol>;
690
691    /// Check if the probe offers an interface to debug ARM chips.
692    fn has_arm_interface(&self) -> bool {
693        false
694    }
695
696    /// Returns a [`JtagAccess`] from the debug probe, if implemented.
697    fn try_as_jtag_probe(&mut self) -> Option<&mut dyn JtagAccess> {
698        None
699    }
700
701    /// Get the dedicated interface to debug ARM chips. To check that the
702    /// probe actually supports this, call [DebugProbe::has_arm_interface] first.
703    fn try_get_arm_debug_interface<'probe>(
704        self: Box<Self>,
705        _sequence: Arc<dyn ArmDebugSequence>,
706    ) -> Result<Box<dyn ArmDebugInterface + 'probe>, (Box<dyn DebugProbe>, ArmError)> {
707        Err((
708            self.into_probe(),
709            DebugProbeError::InterfaceNotAvailable {
710                interface_name: "ARM",
711            }
712            .into(),
713        ))
714    }
715
716    /// Try to get a [`RiscvInterfaceBuilder`] object, which can be used to set up a communication
717    /// interface with chips using the RISC-V architecture.
718    ///
719    /// Ensure that the probe actually supports this by calling
720    /// [DebugProbe::has_riscv_interface] first.
721    fn try_get_riscv_interface_builder<'probe>(
722        &'probe mut self,
723    ) -> Result<Box<dyn RiscvInterfaceBuilder<'probe> + 'probe>, RiscvError> {
724        Err(DebugProbeError::InterfaceNotAvailable {
725            interface_name: "RISC-V",
726        }
727        .into())
728    }
729
730    /// Check if the probe offers an interface to debug RISC-V chips.
731    fn has_riscv_interface(&self) -> bool {
732        false
733    }
734
735    /// Get the dedicated interface to debug Xtensa chips. Ensure that the
736    /// probe actually supports this by calling [DebugProbe::has_xtensa_interface] first.
737    fn try_get_xtensa_interface<'probe>(
738        &'probe mut self,
739        _state: &'probe mut XtensaDebugInterfaceState,
740    ) -> Result<XtensaCommunicationInterface<'probe>, XtensaError> {
741        Err(DebugProbeError::InterfaceNotAvailable {
742            interface_name: "Xtensa",
743        }
744        .into())
745    }
746
747    /// Check if the probe offers an interface to debug Xtensa chips.
748    fn has_xtensa_interface(&self) -> bool {
749        false
750    }
751
752    /// Get a SWO interface from the debug probe.
753    ///
754    /// This is not available on all debug probes.
755    fn get_swo_interface(&self) -> Option<&dyn SwoAccess> {
756        None
757    }
758
759    /// Get a mutable SWO interface from the debug probe.
760    ///
761    /// This is not available on all debug probes.
762    fn get_swo_interface_mut(&mut self) -> Option<&mut dyn SwoAccess> {
763        None
764    }
765
766    /// Boxes itself.
767    fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe>;
768
769    /// Try creating a DAP interface for the given probe.
770    ///
771    /// This is not available on all probes.
772    fn try_as_dap_probe(&mut self) -> Option<&mut dyn DapProbe> {
773        None
774    }
775
776    /// Reads the target voltage in Volts, if possible. Returns `Ok(None)`
777    /// if the probe doesn’t support reading the target voltage.
778    fn get_target_voltage(&mut self) -> Result<Option<f32>, DebugProbeError> {
779        Ok(None)
780    }
781}
782
783impl PartialEq for dyn ProbeFactory {
784    fn eq(&self, other: &Self) -> bool {
785        // Consider ProbeFactory objects equal when their types and data pointers are equal.
786        // Pointer equality is insufficient, because ZST objects may have the same dangling pointer
787        // as their address.
788        self.type_id() == other.type_id()
789            && std::ptr::eq(
790                self as *const _ as *const (),
791                other as *const _ as *const (),
792            )
793    }
794}
795
796/// Gathers some information about a debug probe which was found during a scan.
797#[derive(Debug, Clone, PartialEq)]
798pub struct DebugProbeInfo {
799    /// The name of the debug probe.
800    pub identifier: String,
801    /// The USB vendor ID of the debug probe.
802    pub vendor_id: u16,
803    /// The USB product ID of the debug probe.
804    pub product_id: u16,
805    /// The serial number of the debug probe.
806    pub serial_number: Option<String>,
807
808    /// The USB HID interface which should be used.
809    /// This is necessary for composite HID devices.
810    pub hid_interface: Option<u8>,
811
812    /// A reference to the [`ProbeFactory`] that created this info object.
813    probe_factory: &'static dyn ProbeFactory,
814}
815
816impl std::fmt::Display for DebugProbeInfo {
817    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
818        write!(
819            f,
820            "{} -- {:04x}:{:04x}:{} ({})",
821            self.identifier,
822            self.vendor_id,
823            self.product_id,
824            self.serial_number.as_deref().unwrap_or(""),
825            self.probe_factory,
826        )
827    }
828}
829
830impl DebugProbeInfo {
831    /// Creates a new info struct that uniquely identifies a probe.
832    pub fn new<S: Into<String>>(
833        identifier: S,
834        vendor_id: u16,
835        product_id: u16,
836        serial_number: Option<String>,
837        probe_factory: &'static dyn ProbeFactory,
838        hid_interface: Option<u8>,
839    ) -> Self {
840        Self {
841            identifier: identifier.into(),
842            vendor_id,
843            product_id,
844            serial_number,
845            probe_factory,
846            hid_interface,
847        }
848    }
849
850    /// Open the probe described by this `DebugProbeInfo`.
851    pub fn open(&self) -> Result<Probe, DebugProbeError> {
852        let selector = DebugProbeSelector::from(self);
853        self.probe_factory
854            .open(&selector)
855            .map(Probe::from_specific_probe)
856    }
857
858    /// Returns whether this info was returned by a particular probe factory.
859    pub fn is_probe_type<F: ProbeFactory>(&self) -> bool {
860        self.probe_factory.type_id() == std::any::TypeId::of::<F>()
861    }
862
863    /// Returns a human-readable string describing the probe type.
864    ///
865    /// The exact contents of the string are unstable, this is intended for human consumption only.
866    pub fn probe_type(&self) -> String {
867        self.probe_factory.to_string()
868    }
869}
870
871/// An error which can occur while parsing a [`DebugProbeSelector`].
872#[derive(thiserror::Error, Debug, docsplay::Display)]
873pub enum DebugProbeSelectorParseError {
874    /// Could not parse VID or PID: {0}
875    ParseInt(#[from] std::num::ParseIntError),
876
877    /// The format of the selector is invalid. Please use a string in the form `VID:PID:<Serial>`, where Serial is optional.
878    Format,
879}
880
881/// A struct to describe the way a probe should be selected.
882///
883/// Construct this from a set of info or from a string. The
884/// string has to be in the format "VID:PID:SERIALNUMBER",
885/// where the serial number is optional, and VID and PID are
886/// parsed as hexadecimal numbers.
887///
888/// If SERIALNUMBER exists (i.e. the selector contains a second color) and is empty,
889/// probe-rs will select probes that have no serial number, or where the serial number is empty.
890///
891/// ## Example:
892///
893/// ```
894/// use std::convert::TryInto;
895/// let selector: probe_rs::probe::DebugProbeSelector = "1942:1337:SERIAL".try_into().unwrap();
896///
897/// assert_eq!(selector.vendor_id, 0x1942);
898/// assert_eq!(selector.product_id, 0x1337);
899/// ```
900#[derive(Debug, Clone, PartialEq, Eq, Hash)]
901pub struct DebugProbeSelector {
902    /// The the USB vendor id of the debug probe to be used.
903    pub vendor_id: u16,
904    /// The the USB product id of the debug probe to be used.
905    pub product_id: u16,
906    /// The the serial number of the debug probe to be used.
907    pub serial_number: Option<String>,
908}
909
910impl DebugProbeSelector {
911    pub(crate) fn matches(&self, info: &DeviceInfo) -> bool {
912        self.match_probe_selector(info.vendor_id(), info.product_id(), info.serial_number())
913    }
914
915    /// Check if the given probe info matches this selector.
916    pub fn matches_probe(&self, info: &DebugProbeInfo) -> bool {
917        self.match_probe_selector(
918            info.vendor_id,
919            info.product_id,
920            info.serial_number.as_deref(),
921        )
922    }
923
924    fn match_probe_selector(
925        &self,
926        vendor_id: u16,
927        product_id: u16,
928        serial_number: Option<&str>,
929    ) -> bool {
930        vendor_id == self.vendor_id
931            && product_id == self.product_id
932            && self
933                .serial_number
934                .as_ref()
935                .map(|s| {
936                    if let Some(serial_number) = serial_number {
937                        serial_number == s
938                    } else {
939                        // Match probes without serial number when the
940                        // selector has a third, empty part ("VID:PID:")
941                        s.is_empty()
942                    }
943                })
944                .unwrap_or(true)
945    }
946}
947
948impl TryFrom<&str> for DebugProbeSelector {
949    type Error = DebugProbeSelectorParseError;
950    fn try_from(value: &str) -> Result<Self, Self::Error> {
951        // Split into at most 3 parts: VID, PID, Serial.
952        // We limit the number of splits to allow for colons in the
953        // serial number (EspJtag uses MAC address)
954        let mut split = value.splitn(3, ':');
955
956        let vendor_id = split.next().unwrap(); // First split is always successful
957        let product_id = split.next().ok_or(DebugProbeSelectorParseError::Format)?;
958        let serial_number = split.next().map(|s| s.to_string());
959
960        Ok(DebugProbeSelector {
961            vendor_id: u16::from_str_radix(vendor_id, 16)?,
962            product_id: u16::from_str_radix(product_id, 16)?,
963            serial_number,
964        })
965    }
966}
967
968impl TryFrom<String> for DebugProbeSelector {
969    type Error = DebugProbeSelectorParseError;
970    fn try_from(value: String) -> Result<Self, Self::Error> {
971        TryFrom::<&str>::try_from(&value)
972    }
973}
974
975impl std::str::FromStr for DebugProbeSelector {
976    type Err = DebugProbeSelectorParseError;
977    fn from_str(s: &str) -> Result<Self, Self::Err> {
978        Self::try_from(s)
979    }
980}
981
982impl From<DebugProbeInfo> for DebugProbeSelector {
983    fn from(selector: DebugProbeInfo) -> Self {
984        DebugProbeSelector {
985            vendor_id: selector.vendor_id,
986            product_id: selector.product_id,
987            serial_number: selector.serial_number,
988        }
989    }
990}
991
992impl From<&DebugProbeInfo> for DebugProbeSelector {
993    fn from(selector: &DebugProbeInfo) -> Self {
994        DebugProbeSelector {
995            vendor_id: selector.vendor_id,
996            product_id: selector.product_id,
997            serial_number: selector.serial_number.clone(),
998        }
999    }
1000}
1001
1002impl From<&DebugProbeSelector> for DebugProbeSelector {
1003    fn from(selector: &DebugProbeSelector) -> Self {
1004        selector.clone()
1005    }
1006}
1007
1008impl fmt::Display for DebugProbeSelector {
1009    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1010        write!(f, "{:04x}:{:04x}", self.vendor_id, self.product_id)?;
1011        if let Some(ref sn) = self.serial_number {
1012            write!(f, ":{sn}")?;
1013        }
1014        Ok(())
1015    }
1016}
1017
1018impl From<DebugProbeSelector> for String {
1019    fn from(value: DebugProbeSelector) -> String {
1020        value.to_string()
1021    }
1022}
1023
1024impl Serialize for DebugProbeSelector {
1025    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1026    where
1027        S: Serializer,
1028    {
1029        serializer.serialize_str(&self.to_string())
1030    }
1031}
1032
1033impl<'a> Deserialize<'a> for DebugProbeSelector {
1034    fn deserialize<D>(deserializer: D) -> Result<DebugProbeSelector, D::Error>
1035    where
1036        D: Deserializer<'a>,
1037    {
1038        let s = String::deserialize(deserializer)?;
1039        s.parse().map_err(serde::de::Error::custom)
1040    }
1041}
1042
1043/// Bit-banging interface, ARM edition.
1044///
1045/// This trait (and [RawJtagIo], [JtagAccess]) should not be used by architecture implementations
1046/// directly. Architectures should implement their own protocol interfaces, and use the raw probe
1047/// interfaces (like [RawSwdIo]) to perform the low-level operations AS A FALLBACK. Probes like
1048/// [CmsisDap] should prefer directly implementing the architecture protocols, if they have the
1049/// capability.
1050///
1051/// Currently ARM implements this idea via [crate::architecture::arm::RawDapAccess], which
1052/// is then implemented by [CmsisDap] or a fallback is provided by for
1053/// any [RawSwdIo + JtagAccess](crate::architecture::arm::polyfill) probes.
1054///
1055/// RISC-V is close with its [crate::architecture::riscv::dtm::dtm_access::DtmAccess] trait.
1056///
1057/// [CmsisDap]: crate::probe::cmsisdap::CmsisDap
1058pub(crate) trait RawSwdIo: DebugProbe {
1059    fn swd_io<S>(&mut self, swdio: S) -> Result<Vec<bool>, DebugProbeError>
1060    where
1061        S: IntoIterator<Item = IoSequenceItem>;
1062
1063    fn swj_pins(
1064        &mut self,
1065        pin_out: u32,
1066        pin_select: u32,
1067        pin_wait: u32,
1068    ) -> Result<u32, DebugProbeError>;
1069
1070    fn swd_settings(&self) -> &SwdSettings;
1071
1072    fn probe_statistics(&mut self) -> &mut ProbeStatistics;
1073}
1074
1075/// A trait for implementing low-level JTAG interface operations.
1076pub(crate) trait RawJtagIo: DebugProbe {
1077    /// Returns a mutable reference to the current state.
1078    fn state_mut(&mut self) -> &mut JtagDriverState;
1079
1080    /// Returns the current state.
1081    fn state(&self) -> &JtagDriverState;
1082
1083    /// Shifts a number of bits through the TAP.
1084    fn shift_bits(
1085        &mut self,
1086        tms: impl IntoIterator<Item = bool>,
1087        tdi: impl IntoIterator<Item = bool>,
1088        cap: impl IntoIterator<Item = bool>,
1089    ) -> Result<(), DebugProbeError> {
1090        for ((tms, tdi), cap) in tms.into_iter().zip(tdi.into_iter()).zip(cap.into_iter()) {
1091            self.shift_bit(tms, tdi, cap)?;
1092        }
1093
1094        Ok(())
1095    }
1096
1097    /// Shifts a single bit through the TAP.
1098    ///
1099    /// Drivers may choose, and are encouraged, to buffer bits and flush them
1100    /// in batches for performance reasons.
1101    fn shift_bit(&mut self, tms: bool, tdi: bool, capture: bool) -> Result<(), DebugProbeError>;
1102
1103    /// Returns the bits captured from TDO and clears the capture buffer.
1104    fn read_captured_bits(&mut self) -> Result<BitVec, DebugProbeError>;
1105
1106    /// Resets the JTAG state machine by shifting out a number of high TMS bits.
1107    fn reset_jtag_state_machine(&mut self) -> Result<(), DebugProbeError> {
1108        tracing::debug!("Resetting JTAG chain by setting tms high for 5 bits");
1109
1110        // Reset JTAG chain (5 times TMS high), and enter idle state afterwards
1111        let tms = [true, true, true, true, true, false];
1112        let tdi = std::iter::repeat(true);
1113
1114        self.shift_bits(tms, tdi, std::iter::repeat(false))?;
1115        let response = self.read_captured_bits()?;
1116
1117        tracing::debug!("Response to reset: {response}");
1118
1119        Ok(())
1120    }
1121}
1122
1123#[derive(Debug, Clone, Copy, PartialEq)]
1124pub(crate) enum IoSequenceItem {
1125    Output(bool),
1126    Input,
1127}
1128
1129#[derive(Debug)]
1130pub(crate) struct SwdSettings {
1131    /// Initial number of idle cycles between consecutive writes.
1132    ///
1133    /// When a WAIT response is received, the number of idle cycles
1134    /// will be increased automatically, so this number can be quite
1135    /// low.
1136    pub num_idle_cycles_between_writes: usize,
1137
1138    /// How often a SWD transfer is retried when a WAIT response
1139    /// is received.
1140    pub num_retries_after_wait: usize,
1141
1142    /// When a SWD transfer is retried due to a WAIT response, the idle
1143    /// cycle amount is doubled every time as a backoff. This sets a maximum
1144    /// cap to the cycle amount.
1145    pub max_retry_idle_cycles_after_wait: usize,
1146
1147    /// Number of idle cycles inserted before the result
1148    /// of a write is checked.
1149    ///
1150    /// When performing a write operation, the write can
1151    /// be buffered, meaning that completing the transfer
1152    /// does not mean that the write was performed successfully.
1153    ///
1154    /// To check that all writes have been executed, the
1155    /// `RDBUFF` register can be read from the DP.
1156    ///
1157    /// If any writes are still pending, this read will result in a WAIT response.
1158    /// By adding idle cycles before performing this read, the chance of a
1159    /// WAIT response is smaller.
1160    pub idle_cycles_before_write_verify: usize,
1161
1162    /// Number of idle cycles to insert after a transfer
1163    ///
1164    /// It is recommended that at least 8 idle cycles are
1165    /// inserted.
1166    pub idle_cycles_after_transfer: usize,
1167}
1168
1169impl Default for SwdSettings {
1170    fn default() -> Self {
1171        Self {
1172            num_idle_cycles_between_writes: 2,
1173            num_retries_after_wait: 1000,
1174            max_retry_idle_cycles_after_wait: 128,
1175            idle_cycles_before_write_verify: 8,
1176            idle_cycles_after_transfer: 8,
1177        }
1178    }
1179}
1180
1181/// The state of a bitbanging JTAG driver.
1182///
1183/// This struct tracks the state of the JTAG state machine,  which TAP is currently selected, and
1184/// contains information about the system (like scan chain).
1185#[derive(Debug)]
1186pub(crate) struct JtagDriverState {
1187    pub state: JtagState,
1188    pub expected_scan_chain: Option<Vec<ScanChainElement>>,
1189    pub scan_chain: Vec<ScanChainElement>,
1190    pub chain_params: ChainParams,
1191    /// Idle cycles necessary between consecutive
1192    /// accesses to the DMI register
1193    pub jtag_idle_cycles: usize,
1194}
1195impl JtagDriverState {
1196    fn max_ir_address(&self) -> u32 {
1197        (1 << self.chain_params.irlen) - 1
1198    }
1199}
1200
1201impl Default for JtagDriverState {
1202    fn default() -> Self {
1203        Self {
1204            state: JtagState::Reset,
1205            expected_scan_chain: None,
1206            scan_chain: Vec::new(),
1207            chain_params: ChainParams::default(),
1208            jtag_idle_cycles: 0,
1209        }
1210    }
1211}
1212
1213#[derive(Default, Debug)]
1214pub(crate) struct ProbeStatistics {
1215    /// Number of protocol transfers performed.
1216    ///
1217    /// This includes repeated transfers, and transfers
1218    /// which are automatically added to fulfill
1219    /// protocol requirements, e.g. a read from a
1220    /// DP register will result in two transfers,
1221    /// because the read value is returned in the
1222    /// second transfer
1223    num_transfers: usize,
1224
1225    /// Number of extra transfers added to fullfil protocol
1226    /// requirements. Ideally as low as possible.
1227    num_extra_transfers: usize,
1228
1229    /// Number of calls to the probe IO function.
1230    ///
1231    /// A single call can perform multiple SWD transfers,
1232    /// so this number is ideally a lot lower than then
1233    /// number of SWD transfers.
1234    num_io_calls: usize,
1235
1236    /// Number of SWD wait responses encountered.
1237    num_wait_resp: usize,
1238
1239    /// Number of SWD FAULT responses encountered.
1240    num_faults: usize,
1241}
1242
1243impl ProbeStatistics {
1244    pub fn record_extra_transfer(&mut self) {
1245        self.num_extra_transfers += 1;
1246    }
1247
1248    pub fn record_transfers(&mut self, num_transfers: usize) {
1249        self.num_transfers += num_transfers;
1250    }
1251
1252    pub fn report_io(&mut self) {
1253        self.num_io_calls += 1;
1254    }
1255
1256    pub fn report_swd_response<T>(&mut self, response: &Result<T, DapError>) {
1257        match response {
1258            Err(DapError::FaultResponse) => self.num_faults += 1,
1259            Err(DapError::WaitResponse) => self.num_wait_resp += 1,
1260            // Other errors are not counted right now.
1261            _ => (),
1262        }
1263    }
1264}
1265
1266/// Marker trait for bitbanging JTAG probes.
1267///
1268/// This trait exists to control which probes implement [`JtagAccess`]. In some cases,
1269/// a probe may implement [`RawJtagIo`] but does not want an auto-implemented [JtagAccess].
1270pub(crate) trait AutoImplementJtagAccess: RawJtagIo + 'static {}
1271
1272/// Low-Level access to the JTAG protocol
1273///
1274/// This trait should be implemented by all probes which offer low-level access to
1275/// the JTAG protocol, i.e. direct control over the bytes sent and received.
1276pub trait JtagAccess: DebugProbe {
1277    /// Set the JTAG scan chain information for the target under debug.
1278    ///
1279    /// This allows the probe to know which TAPs are in the scan chain and their
1280    /// position and IR lengths.
1281    ///
1282    /// If the scan chain is provided, and the selected protocol is JTAG, the
1283    /// probe will automatically configure the JTAG interface to match the
1284    /// scan chain configuration without trying to determine the chain at
1285    /// runtime.
1286    ///
1287    /// This is called by the `Session` when attaching to a target.
1288    /// So this does not need to be called manually, unless you want to
1289    /// modify the scan chain. You must be attached to a target to set the
1290    /// scan_chain since the scan chain only applies to the attached target.
1291    fn set_scan_chain(&mut self, scan_chain: &[ScanChainElement]) -> Result<(), DebugProbeError>;
1292
1293    /// Scans `IDCODE` and `IR` length information about the devices on the JTAG chain.
1294    ///
1295    /// If configured, this will use the data from [`Self::set_scan_chain`]. Otherwise, it
1296    /// will try to measure and extract `IR` lengths by driving the JTAG interface.
1297    ///
1298    /// The measured scan chain will be stored in the probe's internal state.
1299    fn scan_chain(&mut self) -> Result<&[ScanChainElement], DebugProbeError>;
1300
1301    /// Shifts a number of bits through the TAP.
1302    fn shift_raw_sequence(&mut self, sequence: JtagSequence) -> Result<BitVec, DebugProbeError>;
1303
1304    /// Executes a TAP reset.
1305    fn tap_reset(&mut self) -> Result<(), DebugProbeError>;
1306
1307    /// For RISC-V, and possibly other interfaces, the JTAG interface has to remain in
1308    /// the idle state for several cycles between consecutive accesses to the DR register.
1309    ///
1310    /// This function configures the number of idle cycles which are inserted after each access.
1311    fn set_idle_cycles(&mut self, idle_cycles: u8) -> Result<(), DebugProbeError>;
1312
1313    /// Return the currently configured idle cycles.
1314    fn idle_cycles(&self) -> u8;
1315
1316    /// Selects the JTAG TAP to be used for communication.
1317    ///
1318    /// The index is the position of the TAP in the scan chain, which can
1319    /// be configured using [`set_scan_chain()`](JtagAccess::set_scan_chain()).
1320    fn select_target(&mut self, index: usize) -> Result<(), DebugProbeError> {
1321        if index != 0 {
1322            return Err(DebugProbeError::NotImplemented {
1323                function_name: "select_jtag_tap",
1324            });
1325        }
1326
1327        Ok(())
1328    }
1329
1330    /// Read a JTAG register.
1331    ///
1332    /// This function emulates a read by performing a write with all zeros to the DR.
1333    fn read_register(&mut self, address: u32, len: u32) -> Result<BitVec, DebugProbeError> {
1334        let data = vec![0u8; len.div_ceil(8) as usize];
1335
1336        self.write_register(address, &data, len)
1337    }
1338
1339    /// Write to a JTAG register
1340    ///
1341    /// This function will perform a write to the IR register, if necessary,
1342    /// to select the correct register, and then to the DR register, to transmit the
1343    /// data. The data shifted out of the DR register will be returned.
1344    fn write_register(
1345        &mut self,
1346        address: u32,
1347        data: &[u8],
1348        len: u32,
1349    ) -> Result<BitVec, DebugProbeError>;
1350
1351    /// Shift a value into the DR JTAG register
1352    ///
1353    /// The data shifted out of the DR register will be returned.
1354    fn write_dr(&mut self, data: &[u8], len: u32) -> Result<BitVec, DebugProbeError>;
1355
1356    /// Executes a sequence of JTAG commands.
1357    fn write_register_batch(
1358        &mut self,
1359        writes: &CommandQueue<JtagCommand>,
1360    ) -> Result<DeferredResultSet<CommandResult>, BatchExecutionError> {
1361        tracing::debug!(
1362            "Using default `JtagAccess::write_register_batch` hurts performance. Please implement proper batching for this probe."
1363        );
1364        let mut results = DeferredResultSet::new();
1365
1366        for (idx, write) in writes.iter() {
1367            match write {
1368                JtagCommand::WriteRegister(write) => {
1369                    match self
1370                        .write_register(write.address, &write.data, write.len)
1371                        .map_err(crate::Error::Probe)
1372                        .and_then(|response| (write.transform)(write, &response))
1373                    {
1374                        Ok(res) => results.push(idx, res),
1375                        Err(e) => return Err(BatchExecutionError::new(e, results)),
1376                    }
1377                }
1378
1379                JtagCommand::ShiftDr(write) => {
1380                    match self
1381                        .write_dr(&write.data, write.len)
1382                        .map_err(crate::Error::Probe)
1383                        .and_then(|response| (write.transform)(write, &response))
1384                    {
1385                        Ok(res) => results.push(idx, res),
1386                        Err(e) => return Err(BatchExecutionError::new(e, results)),
1387                    }
1388                }
1389            }
1390        }
1391
1392        Ok(results)
1393    }
1394}
1395
1396/// A raw JTAG bit sequence.
1397pub struct JtagSequence {
1398    /// TDO capture
1399    pub tdo_capture: bool,
1400
1401    /// TMS value
1402    pub tms: bool,
1403
1404    /// Data to generate on TDI
1405    pub data: BitVec,
1406}
1407
1408/// A low-level JTAG register write command.
1409#[derive(Debug, Clone)]
1410pub struct JtagWriteCommand {
1411    /// The IR register to write to.
1412    pub address: u32,
1413
1414    /// The data to be written to DR.
1415    pub data: Vec<u8>,
1416
1417    /// The number of bits in `data`
1418    pub len: u32,
1419
1420    /// A function to transform the raw response into a [`CommandResult`]
1421    pub transform: fn(&JtagWriteCommand, &BitSlice) -> Result<CommandResult, crate::Error>,
1422}
1423
1424/// A low-level JTAG register write command.
1425#[derive(Debug, Clone)]
1426pub struct ShiftDrCommand {
1427    /// The data to be written to DR.
1428    pub data: Vec<u8>,
1429
1430    /// The number of bits in `data`
1431    pub len: u32,
1432
1433    /// A function to transform the raw response into a [`CommandResult`]
1434    pub transform: fn(&ShiftDrCommand, &BitSlice) -> Result<CommandResult, crate::Error>,
1435}
1436
1437/// A low-level JTAG command.
1438#[derive(Debug, Clone)]
1439pub enum JtagCommand {
1440    /// Write a register.
1441    WriteRegister(JtagWriteCommand),
1442    /// Shift a value into the DR register.
1443    ShiftDr(ShiftDrCommand),
1444}
1445
1446impl From<JtagWriteCommand> for JtagCommand {
1447    fn from(cmd: JtagWriteCommand) -> Self {
1448        JtagCommand::WriteRegister(cmd)
1449    }
1450}
1451
1452impl From<ShiftDrCommand> for JtagCommand {
1453    fn from(cmd: ShiftDrCommand) -> Self {
1454        JtagCommand::ShiftDr(cmd)
1455    }
1456}
1457
1458/// Chain parameters to select a target tap within the chain.
1459#[derive(Clone, Copy, Debug, Default)]
1460pub(crate) struct ChainParams {
1461    pub irpre: usize,
1462    pub irpost: usize,
1463    pub drpre: usize,
1464    pub drpost: usize,
1465    pub irlen: usize,
1466}
1467
1468impl ChainParams {
1469    fn from_jtag_chain(chain: &[ScanChainElement], selected: usize) -> Option<Self> {
1470        let mut params = Self::default();
1471
1472        let mut found = false;
1473        for (index, tap) in chain.iter().enumerate() {
1474            let ir_len = tap.ir_len() as usize;
1475            if index == selected {
1476                params.irlen = ir_len;
1477                found = true;
1478            } else if found {
1479                params.irpost += ir_len;
1480                params.drpost += 1;
1481            } else {
1482                params.irpre += ir_len;
1483                params.drpre += 1;
1484            }
1485        }
1486
1487        found.then_some(params)
1488    }
1489}
1490
1491/// An error that occurred during batched command execution of JTAG commands.
1492#[derive(thiserror::Error, Debug)]
1493pub struct BatchExecutionError {
1494    /// The error that occurred during execution.
1495    #[source]
1496    pub error: crate::Error,
1497
1498    /// The results of the commands that were executed before the error occurred.
1499    pub results: DeferredResultSet<CommandResult>,
1500}
1501
1502impl BatchExecutionError {
1503    pub(crate) fn new(
1504        error: crate::Error,
1505        results: DeferredResultSet<CommandResult>,
1506    ) -> BatchExecutionError {
1507        BatchExecutionError { error, results }
1508    }
1509}
1510
1511impl std::fmt::Display for BatchExecutionError {
1512    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1513        write!(
1514            f,
1515            "Error cause was {}. Successful command count {}",
1516            self.error,
1517            self.results.len()
1518        )
1519    }
1520}
1521
1522/// Results generated by `JtagCommand`s
1523#[derive(Debug, Clone)]
1524pub enum CommandResult {
1525    /// No result
1526    None,
1527
1528    /// A single byte
1529    U8(u8),
1530
1531    /// A single 16-bit word
1532    U16(u16),
1533
1534    /// A single 32-bit word
1535    U32(u32),
1536
1537    /// Multiple bytes
1538    VecU8(Vec<u8>),
1539}
1540
1541impl CommandResult {
1542    /// Returns the result as a `u32` if possible.
1543    ///
1544    /// # Panics
1545    ///
1546    /// Panics if the result is not a `u32`.
1547    pub fn into_u32(self) -> u32 {
1548        match self {
1549            CommandResult::U32(val) => val,
1550            _ => panic!("CommandResult is not a u32"),
1551        }
1552    }
1553
1554    /// Returns the result as a `u8` if possible.
1555    ///
1556    /// # Panics
1557    ///
1558    /// Panics if the result is not a `u8`.
1559    pub fn into_u8(self) -> u8 {
1560        match self {
1561            CommandResult::U8(val) => val,
1562            _ => panic!("CommandResult is not a u8"),
1563        }
1564    }
1565}
1566
1567/// A set of batched commands that will be executed all at once.
1568///
1569/// This list maintains which commands' results can be read by the issuing code, which then
1570/// can be used to skip capturing or processing certain parts of the response.
1571pub struct CommandQueue<T> {
1572    commands: Vec<(DeferredResultIndex, T)>,
1573}
1574
1575impl<T: std::fmt::Debug> std::fmt::Debug for CommandQueue<T> {
1576    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1577        f.debug_struct("CommandQueue")
1578            .field("commands", &self.commands)
1579            .finish()
1580    }
1581}
1582
1583impl<T> Default for CommandQueue<T> {
1584    fn default() -> Self {
1585        Self {
1586            commands: Vec::new(),
1587        }
1588    }
1589}
1590
1591impl<T> CommandQueue<T> {
1592    /// Creates a new empty queue.
1593    pub fn new() -> Self {
1594        Self::default()
1595    }
1596
1597    /// Schedules a command for later execution.
1598    ///
1599    /// Returns a token value that can be used to retrieve the result of the command.
1600    pub fn schedule(&mut self, command: impl Into<T>) -> DeferredResultIndex {
1601        let index = DeferredResultIndex::new();
1602        self.commands.push((index.clone(), command.into()));
1603        index
1604    }
1605
1606    /// Returns the number of commands in the queue.
1607    pub fn len(&self) -> usize {
1608        self.commands.len()
1609    }
1610
1611    /// Returns whether the queue is empty.
1612    pub fn is_empty(&self) -> bool {
1613        self.commands.is_empty()
1614    }
1615
1616    pub(crate) fn iter(&self) -> impl Iterator<Item = &(DeferredResultIndex, T)> {
1617        self.commands.iter()
1618    }
1619
1620    /// Removes the first `len` number of commands from the batch.
1621    pub(crate) fn consume(&mut self, len: usize) {
1622        self.commands.drain(..len);
1623    }
1624}
1625
1626/// The set of results returned by executing a batched command.
1627pub struct DeferredResultSet<T>(HashMap<DeferredResultIndex, T>);
1628
1629impl<T: std::fmt::Debug> std::fmt::Debug for DeferredResultSet<T> {
1630    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1631        f.debug_tuple("DeferredResultSet").field(&self.0).finish()
1632    }
1633}
1634
1635impl<T> Default for DeferredResultSet<T> {
1636    fn default() -> Self {
1637        Self(HashMap::default())
1638    }
1639}
1640
1641impl<T> DeferredResultSet<T> {
1642    /// Creates a new empty result set.
1643    pub fn new() -> Self {
1644        Self::default()
1645    }
1646
1647    /// Creates a new empty result set with the given capacity.
1648    pub fn with_capacity(capacity: usize) -> Self {
1649        Self(HashMap::with_capacity(capacity))
1650    }
1651
1652    pub(crate) fn push(&mut self, idx: &DeferredResultIndex, result: T) {
1653        self.0.insert(idx.clone(), result);
1654    }
1655
1656    /// Returns the number of results in the set.
1657    pub fn len(&self) -> usize {
1658        self.0.len()
1659    }
1660
1661    /// Returns whether the set is empty.
1662    pub fn is_empty(&self) -> bool {
1663        self.0.is_empty()
1664    }
1665
1666    pub(crate) fn merge_from(&mut self, other: DeferredResultSet<T>) {
1667        self.0.extend(other.0);
1668        self.0.retain(|k, _| k.should_capture());
1669    }
1670
1671    /// Takes a result from the set.
1672    pub fn take(&mut self, index: DeferredResultIndex) -> Result<T, DeferredResultIndex> {
1673        self.0.remove(&index).ok_or(index)
1674    }
1675}
1676
1677/// An index type used to retrieve the result of a deferred command.
1678///
1679/// This type can detect if the result of a command is not used.
1680#[derive(Eq)]
1681pub struct DeferredResultIndex(Arc<()>);
1682
1683impl PartialEq for DeferredResultIndex {
1684    fn eq(&self, other: &Self) -> bool {
1685        Arc::ptr_eq(&self.0, &other.0)
1686    }
1687}
1688
1689impl fmt::Debug for DeferredResultIndex {
1690    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1691        f.debug_tuple("DeferredResultIndex")
1692            .field(&self.id())
1693            .finish()
1694    }
1695}
1696
1697impl DeferredResultIndex {
1698    // Intentionally private. User code must not be able to create these.
1699    fn new() -> Self {
1700        Self(Arc::new(()))
1701    }
1702
1703    fn id(&self) -> usize {
1704        Arc::as_ptr(&self.0) as usize
1705    }
1706
1707    pub(crate) fn should_capture(&self) -> bool {
1708        // Both the queue and the user code may hold on to at most one of the references. The queue
1709        // execution will be able to detect if the user dropped their read reference, meaning
1710        // the read data would be inaccessible.
1711        Arc::strong_count(&self.0) > 1
1712    }
1713
1714    // Intentionally private. User code must not be able to clone these.
1715    fn clone(&self) -> Self {
1716        Self(self.0.clone())
1717    }
1718}
1719
1720impl std::hash::Hash for DeferredResultIndex {
1721    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1722        self.id().hash(state)
1723    }
1724}
1725
1726/// The method that should be used for attaching.
1727#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Serialize, Deserialize)]
1728pub enum AttachMethod {
1729    /// Attach normally with no special behavior.
1730    #[default]
1731    Normal,
1732    /// Attach to the target while it is in reset.
1733    ///
1734    /// This is required on targets that can remap SWD pins or disable the SWD interface in sleep.
1735    UnderReset,
1736}
1737
1738#[cfg(test)]
1739mod test {
1740    use super::*;
1741
1742    #[test]
1743    fn test_is_probe_factory() {
1744        let probe_info = DebugProbeInfo::new(
1745            "Mock probe",
1746            0x12,
1747            0x23,
1748            Some("mock_serial".to_owned()),
1749            &ftdi::FtdiProbeFactory,
1750            None,
1751        );
1752
1753        assert!(probe_info.is_probe_type::<ftdi::FtdiProbeFactory>());
1754        assert!(!probe_info.is_probe_type::<espusbjtag::EspUsbJtagFactory>());
1755    }
1756
1757    #[test]
1758    fn test_parsing_many_colons() {
1759        let selector: DebugProbeSelector = "303a:1001:DC:DA:0C:D3:FE:D8".try_into().unwrap();
1760
1761        assert_eq!(selector.vendor_id, 0x303a);
1762        assert_eq!(selector.product_id, 0x1001);
1763        assert_eq!(
1764            selector.serial_number,
1765            Some("DC:DA:0C:D3:FE:D8".to_string())
1766        );
1767    }
1768
1769    #[test]
1770    fn missing_serial_is_none() {
1771        let selector: DebugProbeSelector = "303a:1001".try_into().unwrap();
1772
1773        assert_eq!(selector.vendor_id, 0x303a);
1774        assert_eq!(selector.product_id, 0x1001);
1775        assert_eq!(selector.serial_number, None);
1776
1777        let matches = selector.match_probe_selector(0x303a, 0x1001, None);
1778        let matches_with_serial = selector.match_probe_selector(0x303a, 0x1001, Some("serial"));
1779        assert!(matches);
1780        assert!(matches_with_serial);
1781    }
1782
1783    #[test]
1784    fn empty_serial_is_some() {
1785        let selector: DebugProbeSelector = "303a:1001:".try_into().unwrap();
1786
1787        assert_eq!(selector.vendor_id, 0x303a);
1788        assert_eq!(selector.product_id, 0x1001);
1789        assert_eq!(selector.serial_number, Some(String::new()));
1790
1791        let matches = selector.match_probe_selector(0x303a, 0x1001, None);
1792        let matches_with_serial = selector.match_probe_selector(0x303a, 0x1001, Some("serial"));
1793        assert!(matches);
1794        assert!(!matches_with_serial);
1795    }
1796}