@@ -7,12 +7,14 @@ use clap::Args;
77use regex:: Regex ;
88use std:: any:: Any ;
99use std:: fs:: File ;
10+ use std:: io:: Write ;
1011use std:: marker:: Unpin ;
1112use std:: time:: Duration ;
1213use tokio:: io:: { AsyncRead , AsyncReadExt } ;
1314
1415use opentitanlib:: app:: TransportWrapper ;
1516use opentitanlib:: app:: command:: CommandDispatch ;
17+ use opentitanlib:: io:: console:: Broadcaster ;
1618use opentitanlib:: io:: uart:: { Uart , UartParams } ;
1719use opentitanlib:: transport:: Capability ;
1820use opentitanlib:: uart:: console:: { ExitStatus , UartConsole } ;
8991 }
9092}
9193
94+ /// Takes input from a console and write to an output.
95+ async fn pipe_output < T , W > ( device : & T , w : & mut W ) -> Result < ( ) >
96+ where
97+ T : Uart + ?Sized ,
98+ W : Write ,
99+ {
100+ let mut buf = [ 0u8 ; 256 ] ;
101+
102+ loop {
103+ let len = std:: future:: poll_fn ( |cx| device. poll_read ( cx, & mut buf) ) . await ?;
104+ w. write_all ( & buf[ ..len] ) ?;
105+ }
106+ }
107+
92108impl CommandDispatch for Console {
93109 fn run (
94110 & self ,
@@ -104,6 +120,8 @@ impl CommandDispatch for Console {
104120 uart. write ( send. as_bytes ( ) ) ?;
105121 }
106122
123+ let mut logfile = self . logfile . as_ref ( ) . map ( File :: create) . transpose ( ) ?;
124+
107125 // Set up resources specified by the command line parameters.
108126 let mut console = UartConsole :: new (
109127 self . timeout ,
@@ -116,7 +134,6 @@ impl CommandDispatch for Console {
116134 . map ( |s| Regex :: new ( s. as_str ( ) ) )
117135 . transpose ( ) ?,
118136 ) ;
119- console. logfile = self . logfile . as_ref ( ) . map ( File :: create) . transpose ( ) ?;
120137 console. timestamp = self . timestamp ;
121138
122139 // Put the terminal into raw mode. The tty guard will restore the
@@ -134,6 +151,8 @@ impl CommandDispatch for Console {
134151
135152 let status = transport. relinquish_exclusive_access ( || {
136153 opentitanlib:: util:: runtime:: block_on ( async {
154+ let uart_rx = Broadcaster :: new ( uart. clone ( ) ) ;
155+
137156 let tx = async {
138157 if let Some ( stdin) = stdin. as_mut ( ) {
139158 process_input ( & * uart, stdin) . await
@@ -142,14 +161,23 @@ impl CommandDispatch for Console {
142161 }
143162 } ;
144163
164+ let log_to_file = async {
165+ if let Some ( file) = logfile. as_mut ( ) {
166+ pipe_output ( & uart_rx. clone ( ) , file) . await
167+ } else {
168+ std:: future:: pending ( ) . await
169+ }
170+ } ;
171+
145172 let rx = async {
146173 console
147- . interact_async ( & * uart , Some ( & mut std:: io:: stdout ( ) ) )
174+ . interact_async ( & uart_rx , Some ( & mut std:: io:: stdout ( ) ) )
148175 . await
149176 } ;
150177
151178 Result :: < _ > :: Ok ( tokio:: select! {
152179 v = tx => Err ( v?) ,
180+ v = log_to_file => Err ( v?) ,
153181 v = rx => Ok ( v?) ,
154182 } )
155183 } )
0 commit comments