probe_rs/probe/ch347usbjtag/
mod.rs

1//! ch347 is a usb bus converter that provides UART, I2C and SPI and Jtag/Swd interface
2mod protocol;
3
4use protocol::Ch347UsbJtagDevice;
5
6use crate::{
7    architecture::{
8        arm::{ArmCommunicationInterface, communication_interface::DapProbe},
9        riscv::dtm::jtag_dtm::JtagDtmBuilder,
10        xtensa::communication_interface::XtensaCommunicationInterface,
11    },
12    probe::{DebugProbe, ProbeFactory},
13};
14
15use super::{
16    AutoImplementJtagAccess, DebugProbeError, IoSequenceItem, JtagDriverState, ProbeStatistics,
17    RawJtagIo, RawSwdIo, SwdSettings,
18};
19
20/// A factory for creating [`Ch347UsbJtag`] instances.
21#[derive(Debug)]
22pub struct Ch347UsbJtagFactory;
23
24impl std::fmt::Display for Ch347UsbJtagFactory {
25    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26        f.write_str("Ch347UsbJtag")
27    }
28}
29
30/// An Ch347-based debug probe.
31#[derive(Debug)]
32pub struct Ch347UsbJtag {
33    device: Ch347UsbJtagDevice,
34    jtag_state: JtagDriverState,
35    probe_statistics: ProbeStatistics,
36    swd_settings: SwdSettings,
37}
38
39impl ProbeFactory for Ch347UsbJtagFactory {
40    fn open(
41        &self,
42        selector: &super::DebugProbeSelector,
43    ) -> Result<Box<dyn super::DebugProbe>, super::DebugProbeError> {
44        let ch347 = Ch347UsbJtagDevice::new_from_selector(selector)?;
45
46        tracing::info!("Found ch347 device");
47        Ok(Box::new(Ch347UsbJtag {
48            device: ch347,
49            jtag_state: JtagDriverState::default(),
50            probe_statistics: ProbeStatistics::default(),
51            swd_settings: SwdSettings::default(),
52        }))
53    }
54
55    fn list_probes(&self) -> Vec<super::DebugProbeInfo> {
56        protocol::list_ch347usbjtag_devices()
57    }
58}
59
60impl RawJtagIo for Ch347UsbJtag {
61    fn shift_bit(
62        &mut self,
63        tms: bool,
64        tdi: bool,
65        capture: bool,
66    ) -> Result<(), super::DebugProbeError> {
67        self.jtag_state.state.update(tms);
68        self.device.shift_bit(tms, tdi, capture)?;
69
70        Ok(())
71    }
72
73    fn read_captured_bits(&mut self) -> Result<bitvec::prelude::BitVec, super::DebugProbeError> {
74        self.device.read_captured_bits()
75    }
76
77    fn state_mut(&mut self) -> &mut JtagDriverState {
78        &mut self.jtag_state
79    }
80
81    fn state(&self) -> &JtagDriverState {
82        &self.jtag_state
83    }
84}
85
86impl RawSwdIo for Ch347UsbJtag {
87    fn swd_io<S>(&mut self, _swdio: S) -> Result<Vec<bool>, DebugProbeError>
88    where
89        S: IntoIterator<Item = IoSequenceItem>,
90    {
91        Err(DebugProbeError::NotImplemented {
92            function_name: "swd_io",
93        })
94    }
95
96    fn swj_pins(
97        &mut self,
98        _pin_out: u32,
99        _pin_select: u32,
100        _pin_wait: u32,
101    ) -> Result<u32, DebugProbeError> {
102        Err(DebugProbeError::CommandNotSupportedByProbe {
103            command_name: "swj_pins",
104        })
105    }
106
107    fn swd_settings(&self) -> &SwdSettings {
108        &self.swd_settings
109    }
110
111    fn probe_statistics(&mut self) -> &mut ProbeStatistics {
112        &mut self.probe_statistics
113    }
114}
115
116impl AutoImplementJtagAccess for Ch347UsbJtag {}
117impl DapProbe for Ch347UsbJtag {}
118
119impl DebugProbe for Ch347UsbJtag {
120    fn get_name(&self) -> &str {
121        "CH347 USB Jtag"
122    }
123
124    fn speed_khz(&self) -> u32 {
125        self.device.speed_khz()
126    }
127
128    fn set_speed(&mut self, speed_khz: u32) -> Result<u32, super::DebugProbeError> {
129        Ok(self.device.set_speed_khz(speed_khz))
130    }
131
132    fn attach(&mut self) -> Result<(), super::DebugProbeError> {
133        self.device.attach()
134    }
135
136    fn detach(&mut self) -> Result<(), crate::Error> {
137        Ok(())
138    }
139
140    fn target_reset(&mut self) -> Result<(), super::DebugProbeError> {
141        // TODO
142        Err(DebugProbeError::NotImplemented {
143            function_name: "target_reset",
144        })
145    }
146    fn target_reset_assert(&mut self) -> Result<(), super::DebugProbeError> {
147        // TODO
148        Err(DebugProbeError::NotImplemented {
149            function_name: "target_reset_assert",
150        })
151    }
152
153    fn target_reset_deassert(&mut self) -> Result<(), super::DebugProbeError> {
154        // TODO
155        Err(DebugProbeError::NotImplemented {
156            function_name: "target_reset_deassert",
157        })
158    }
159
160    fn select_protocol(
161        &mut self,
162        protocol: super::WireProtocol,
163    ) -> Result<(), super::DebugProbeError> {
164        // ch347 is support swd, wait...
165        // TODO
166        if protocol != super::WireProtocol::Jtag {
167            Err(DebugProbeError::UnsupportedProtocol(protocol))
168        } else {
169            Ok(())
170        }
171    }
172
173    fn active_protocol(&self) -> Option<super::WireProtocol> {
174        // TODO
175        Some(super::WireProtocol::Jtag)
176    }
177
178    fn into_probe(self: Box<Self>) -> Box<dyn DebugProbe> {
179        self
180    }
181
182    fn try_as_jtag_probe(&mut self) -> Option<&mut dyn super::JtagAccess> {
183        Some(self)
184    }
185
186    fn has_arm_interface(&self) -> bool {
187        true
188    }
189
190    fn try_get_arm_debug_interface<'probe>(
191        self: Box<Self>,
192        sequence: std::sync::Arc<dyn crate::architecture::arm::sequences::ArmDebugSequence>,
193    ) -> Result<
194        Box<dyn crate::architecture::arm::ArmDebugInterface + 'probe>,
195        (Box<dyn DebugProbe>, crate::architecture::arm::ArmError),
196    > {
197        Ok(ArmCommunicationInterface::create(self, sequence, true))
198    }
199
200    fn has_riscv_interface(&self) -> bool {
201        true
202    }
203
204    fn try_get_riscv_interface_builder<'probe>(
205        &'probe mut self,
206    ) -> Result<
207        Box<
208            dyn crate::architecture::riscv::communication_interface::RiscvInterfaceBuilder<'probe>
209                + 'probe,
210        >,
211        crate::architecture::riscv::communication_interface::RiscvError,
212    > {
213        Ok(Box::new(JtagDtmBuilder::new(self)))
214    }
215
216    fn has_xtensa_interface(&self) -> bool {
217        true
218    }
219
220    fn try_get_xtensa_interface<'probe>(
221        &'probe mut self,
222        state: &'probe mut crate::architecture::xtensa::communication_interface::XtensaDebugInterfaceState,
223    ) -> Result<
224        crate::architecture::xtensa::communication_interface::XtensaCommunicationInterface<'probe>,
225        crate::architecture::xtensa::communication_interface::XtensaError,
226    > {
227        Ok(XtensaCommunicationInterface::new(self, state))
228    }
229}