@@ -2,14 +2,15 @@ use std::time::Duration;
22
33use probe_rs:: probe:: DebugProbeInfo ;
44use probe_rs:: { Permissions , Session } ;
5+ use tokio:: io:: AsyncWriteExt ;
56use tokio_serial:: { FlowControl , Parity , SerialPort , SerialStream , StopBits } ;
67
78use crate :: errors:: TockloaderError ;
89
9- pub enum ConnectionInfo {
10- SerialInfo ( String , SerialTargetInfo ) ,
11- ProbeInfo ( DebugProbeInfo , ProbeTargetInfo ) ,
12- }
10+ // pub enum ConnectionInfo {
11+ // SerialInfo(String, SerialTargetInfo),
12+ // ProbeInfo(DebugProbeInfo, ProbeTargetInfo),
13+ // }
1314
1415pub struct ProbeTargetInfo {
1516 pub chip : String ,
@@ -46,65 +47,110 @@ impl Default for SerialTargetInfo {
4647 }
4748}
4849
49- // TODO(george-cosma): trait? and 2 struct ProbeConnection and SerialConection?
50- #[ allow( clippy:: large_enum_variant) ]
51- pub enum Connection {
52- ProbeRS {
53- session : Session ,
54- info : ProbeTargetInfo ,
55- } ,
56- Serial {
57- stream : SerialStream ,
58- info : SerialTargetInfo ,
59- } ,
50+ pub trait Connection {
51+ async fn open ( & mut self ) -> Result < ( ) , TockloaderError > ;
52+ /// Closes the connection, if it is open. If it is not open, it does
53+ /// nothing. On error the state of the connection is unknown and calling
54+ /// `open` or any other method is undefined behavior.
55+ async fn close ( & mut self ) -> Result < ( ) , TockloaderError > ;
56+ fn is_open ( & self ) -> bool ;
57+ }
58+
59+ pub struct ProbeRSConnection {
60+ session : Option < Session > ,
61+ /// Used both to open new conections but also used during the session to
62+ /// provide information about the target
63+ target_info : ProbeTargetInfo ,
64+ /// Only used for opening a new connection
65+ debug_probe : DebugProbeInfo ,
6066}
6167
62- impl Connection {
63- pub fn open ( info : ConnectionInfo ) -> Result < Connection , TockloaderError > {
64- match info {
65- ConnectionInfo :: SerialInfo ( path, target_info) => {
66- let builder = tokio_serial:: new ( path, target_info. baud_rate ) ;
67- match SerialStream :: open ( & builder) {
68- Ok ( mut stream) => {
69- stream
70- . set_parity ( target_info. parity )
71- . map_err ( TockloaderError :: SerialInitializationError ) ?;
72- stream
73- . set_stop_bits ( target_info. stop_bits )
74- . map_err ( TockloaderError :: SerialInitializationError ) ?;
75- stream
76- . set_flow_control ( target_info. flow_control )
77- . map_err ( TockloaderError :: SerialInitializationError ) ?;
78- stream
79- . set_timeout ( target_info. timeout )
80- . map_err ( TockloaderError :: SerialInitializationError ) ?;
81- stream
82- . write_request_to_send ( target_info. request_to_send )
83- . map_err ( TockloaderError :: SerialInitializationError ) ?;
84- stream
85- . write_data_terminal_ready ( target_info. data_terminal_ready )
86- . map_err ( TockloaderError :: SerialInitializationError ) ?;
87- Ok ( Connection :: Serial {
88- stream,
89- info : target_info,
90- } )
91- }
92- Err ( e) => Err ( TockloaderError :: SerialInitializationError ( e) ) ,
93- }
94- }
95- ConnectionInfo :: ProbeInfo ( probe_info, target_info) => {
96- let probe = probe_info
97- . open ( )
98- . map_err ( TockloaderError :: ProbeRsInitializationError ) ?;
99-
100- match probe. attach ( & target_info. chip , Permissions :: default ( ) ) {
101- Ok ( session) => Ok ( Connection :: ProbeRS {
102- session,
103- info : target_info,
104- } ) ,
105- Err ( e) => Err ( TockloaderError :: ProbeRsCommunicationError ( e) ) ,
106- }
107- }
68+ impl ProbeRSConnection {
69+ pub fn new ( debug_probe : DebugProbeInfo , target_info : ProbeTargetInfo ) -> Self {
70+ Self {
71+ session : None ,
72+ target_info,
73+ debug_probe,
10874 }
10975 }
11076}
77+
78+ impl Connection for ProbeRSConnection {
79+ async fn open ( & mut self ) -> Result < ( ) , TockloaderError > {
80+ let probe = self
81+ . debug_probe
82+ . open ( )
83+ . map_err ( TockloaderError :: ProbeRsInitializationError ) ?;
84+
85+ self . session = Some (
86+ probe
87+ . attach ( & self . target_info . chip , Permissions :: default ( ) )
88+ . map_err ( TockloaderError :: ProbeRsCommunicationError ) ?,
89+ ) ;
90+
91+ Ok ( ( ) )
92+ }
93+
94+ async fn close ( & mut self ) -> Result < ( ) , TockloaderError > {
95+ // Session implements Drop, so we don't need to explicitly close it.
96+ self . session = None ;
97+ Ok ( ( ) )
98+ }
99+
100+ fn is_open ( & self ) -> bool {
101+ self . session . is_some ( )
102+ }
103+ }
104+
105+ pub struct SerialConnection {
106+ stream : Option < SerialStream > ,
107+ /// Used both to open new connections but also used during the session to
108+ /// provide information about the target
109+ target_info : SerialTargetInfo ,
110+ /// Path to the serial port. This is only used for opening a new connection.
111+ port : String ,
112+ }
113+
114+ impl SerialConnection {
115+ pub fn new ( port : String , target_info : SerialTargetInfo ) -> Self {
116+ Self {
117+ stream : None ,
118+ target_info,
119+ port,
120+ }
121+ }
122+ }
123+
124+ impl Connection for SerialConnection {
125+ async fn open ( & mut self ) -> Result < ( ) , TockloaderError > {
126+ let builder = tokio_serial:: new ( & self . port , self . target_info . baud_rate )
127+ . parity ( self . target_info . parity )
128+ . stop_bits ( self . target_info . stop_bits )
129+ . flow_control ( self . target_info . flow_control )
130+ . timeout ( self . target_info . timeout ) ;
131+
132+ let mut stream =
133+ SerialStream :: open ( & builder) . map_err ( TockloaderError :: SerialInitializationError ) ?;
134+
135+ stream
136+ . write_request_to_send ( self . target_info . request_to_send )
137+ . map_err ( TockloaderError :: SerialInitializationError ) ?;
138+ stream
139+ . write_data_terminal_ready ( self . target_info . data_terminal_ready )
140+ . map_err ( TockloaderError :: SerialInitializationError ) ?;
141+
142+ self . stream = Some ( stream) ;
143+ Ok ( ( ) )
144+ }
145+
146+ async fn close ( & mut self ) -> Result < ( ) , TockloaderError > {
147+ if let Some ( mut stream) = self . stream . take ( ) {
148+ stream. shutdown ( ) . await ;
149+ }
150+ Ok ( ( ) )
151+ }
152+
153+ fn is_open ( & self ) -> bool {
154+ self . stream . is_some ( )
155+ }
156+ }
0 commit comments