Skip to content

Commit f00747a

Browse files
committed
[opentitanlib] remove UartConsole stdin handling
The feature is only ever used by `opentitantool console`, so have this feature implemented there instead. Signed-off-by: Gary Guo <[email protected]>
1 parent 6e74b8c commit f00747a

File tree

20 files changed

+95
-103
lines changed

20 files changed

+95
-103
lines changed

sw/host/opentitanlib/src/test_utils/rpc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ where
7777
} else {
7878
None
7979
};
80-
let result = console.interact(device, None, out)?;
80+
let result = console.interact(device, out)?;
8181
println!();
8282
match result {
8383
ExitStatus::ExitSuccess => {

sw/host/opentitanlib/src/uart/console.rs

Lines changed: 8 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
// SPDX-License-Identifier: Apache-2.0
44

5-
use anyhow::{Result, anyhow};
6-
use regex::{Captures, Regex};
75
use std::fs::File;
86
use std::io::Write;
9-
use std::os::fd::AsFd;
107
use std::time::{Duration, SystemTime};
118

12-
use tokio::io::AsyncReadExt;
9+
use anyhow::{Result, anyhow};
10+
use regex::{Captures, Regex};
1311

1412
use crate::io::console::{ConsoleDevice, ConsoleError};
1513

@@ -21,7 +19,6 @@ pub struct UartConsole {
2119
pub timestamp: bool,
2220
buffer: String,
2321
newline: bool,
24-
break_en: bool,
2522
}
2623

2724
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -33,13 +30,7 @@ pub enum ExitStatus {
3330
ExitFailure,
3431
}
3532

36-
// Creates a vtable for implementors of Read and AsFd traits.
37-
pub trait ReadAsFd: tokio::io::AsyncRead + AsFd + std::marker::Unpin {}
38-
impl<T: tokio::io::AsyncRead + AsFd + std::marker::Unpin> ReadAsFd for T {}
39-
4033
impl UartConsole {
41-
const CTRL_B: u8 = 2;
42-
const CTRL_C: u8 = 3;
4334
const BUFFER_LEN: usize = 32768;
4435

4536
pub fn new(
@@ -55,43 +46,28 @@ impl UartConsole {
5546
timestamp: true,
5647
buffer: String::new(),
5748
newline: true,
58-
break_en: false,
5949
}
6050
}
6151

6252
// Runs an interactive console until CTRL_C is received.
63-
pub fn interact<T>(
64-
&mut self,
65-
device: &T,
66-
stdin: Option<&mut dyn ReadAsFd>,
67-
stdout: Option<&mut dyn Write>,
68-
) -> Result<ExitStatus>
53+
pub fn interact<T>(&mut self, device: &T, stdout: Option<&mut dyn Write>) -> Result<ExitStatus>
6954
where
7055
T: ConsoleDevice + ?Sized,
7156
{
72-
crate::util::runtime::block_on(self.interact_async(device, stdin, stdout))
57+
crate::util::runtime::block_on(self.interact_async(device, stdout))
7358
}
7459

7560
// Runs an interactive console until CTRL_C is received. Uses `mio` library to simultaneously
7661
// wait for data from UART or from stdin, without need for timeouts and repeated calls.
77-
async fn interact_async<T>(
62+
pub async fn interact_async<T>(
7863
&mut self,
7964
device: &T,
80-
mut stdin: Option<&mut dyn ReadAsFd>,
8165
mut stdout: Option<&mut dyn Write>,
8266
) -> Result<ExitStatus>
8367
where
8468
T: ConsoleDevice + ?Sized,
8569
{
86-
let mut break_en = self.break_en;
8770
let timeout = self.timeout;
88-
let tx = async {
89-
if let Some(stdin) = stdin.as_mut() {
90-
Self::process_input(&mut break_en, device, stdin).await
91-
} else {
92-
std::future::pending().await
93-
}
94-
};
9571
let rx = async {
9672
loop {
9773
self.uart_read(device, &mut stdout).await?;
@@ -121,13 +97,10 @@ impl UartConsole {
12197
}
12298
};
12399

124-
let r = tokio::select! {
125-
v = tx => v,
100+
tokio::select! {
126101
v = rx => v,
127102
_ = timeout => Ok(ExitStatus::Timeout),
128-
};
129-
self.break_en = break_en;
130-
r
103+
}
131104
}
132105

133106
/// Returns `true` if any regular expressions are used to match the streamed output. If so,
@@ -185,41 +158,6 @@ impl UartConsole {
185158
Ok(())
186159
}
187160

188-
async fn process_input<T>(
189-
break_en: &mut bool,
190-
device: &T,
191-
stdin: &mut dyn ReadAsFd,
192-
) -> Result<ExitStatus>
193-
where
194-
T: ConsoleDevice + ?Sized,
195-
{
196-
loop {
197-
let mut buf = [0u8; 256];
198-
let len = stdin.read(&mut buf).await?;
199-
if len == 1 {
200-
if buf[0] == UartConsole::CTRL_C {
201-
return Ok(ExitStatus::CtrlC);
202-
}
203-
if buf[0] == UartConsole::CTRL_B {
204-
*break_en = !*break_en;
205-
eprint!(
206-
"\r\n{} break",
207-
if *break_en { "Setting" } else { "Clearing" }
208-
);
209-
let b = device.set_break(*break_en);
210-
if b.is_err() {
211-
eprint!(": {:?}", b);
212-
}
213-
eprint!("\r\n");
214-
continue;
215-
}
216-
}
217-
if len > 0 {
218-
device.write(&buf[..len])?;
219-
}
220-
}
221-
}
222-
223161
pub fn captures(&self, status: ExitStatus) -> Option<Captures<'_>> {
224162
match status {
225163
ExitStatus::ExitSuccess => self
@@ -243,7 +181,7 @@ impl UartConsole {
243181
{
244182
let mut console = UartConsole::new(Some(timeout), Some(Regex::new(rx)?), None);
245183
let mut stdout = std::io::stdout();
246-
let result = console.interact(device, None, Some(&mut stdout))?;
184+
let result = console.interact(device, Some(&mut stdout))?;
247185
println!();
248186
match result {
249187
ExitStatus::ExitSuccess => {

sw/host/opentitanlib/src/util/rom_detect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl RomDetect {
3030

3131
pub fn detect(&mut self, uart: &dyn Uart) -> Result<bool> {
3232
let t0 = Instant::now();
33-
let rc = self.console.interact(uart, None, None)?;
33+
let rc = self.console.interact(uart, None)?;
3434
let t1 = Instant::now();
3535
log::debug!("detect exit={:?}, duration={:?}", rc, t1 - t0);
3636
if let Some(cap) = self.console.captures(ExitStatus::ExitSuccess) {

sw/host/opentitantool/src/command/console.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ use clap::Args;
77
use regex::Regex;
88
use std::any::Any;
99
use std::fs::File;
10+
use std::marker::Unpin;
1011
use std::time::Duration;
12+
use tokio::io::{AsyncRead, AsyncReadExt};
1113

1214
use opentitanlib::app::TransportWrapper;
1315
use opentitanlib::app::command::CommandDispatch;
16+
use opentitanlib::io::console::ConsoleDevice;
1417
use opentitanlib::io::uart::UartParams;
1518
use opentitanlib::transport::Capability;
1619
use opentitanlib::uart::console::{ExitStatus, UartConsole};
@@ -52,6 +55,42 @@ pub struct Console {
5255
exit_failure: Option<String>,
5356
}
5457

58+
const CTRL_B: u8 = 2;
59+
const CTRL_C: u8 = 3;
60+
61+
/// Takes input from an input stream and send it to a console device. Breaks are handled.
62+
async fn process_input<T, R: AsyncRead + Unpin>(device: &T, stdin: &mut R) -> Result<ExitStatus>
63+
where
64+
T: ConsoleDevice + ?Sized,
65+
{
66+
let mut break_en = false;
67+
loop {
68+
let mut buf = [0u8; 256];
69+
let len = stdin.read(&mut buf).await?;
70+
if len == 1 {
71+
if buf[0] == CTRL_C {
72+
return Ok(ExitStatus::CtrlC);
73+
}
74+
if buf[0] == CTRL_B {
75+
break_en = !break_en;
76+
eprint!(
77+
"\r\n{} break",
78+
if break_en { "Setting" } else { "Clearing" }
79+
);
80+
let b = device.set_break(break_en);
81+
if b.is_err() {
82+
eprint!(": {:?}", b);
83+
}
84+
eprint!("\r\n");
85+
continue;
86+
}
87+
}
88+
if len > 0 {
89+
device.write(&buf[..len])?;
90+
}
91+
}
92+
}
93+
5594
impl CommandDispatch for Console {
5695
fn run(
5796
&self,
@@ -97,7 +136,22 @@ impl CommandDispatch for Console {
97136
}
98137

99138
transport.relinquish_exclusive_access(|| {
100-
console.interact(&*uart, stdin.as_mut().map(|x| x as _), Some(&mut stdout))
139+
opentitanlib::util::runtime::block_on(async {
140+
let tx = async {
141+
if let Some(stdin) = stdin.as_mut() {
142+
process_input(&*uart, stdin).await
143+
} else {
144+
std::future::pending().await
145+
}
146+
};
147+
148+
let rx = console.interact_async(&*uart, Some(&mut stdout));
149+
150+
tokio::select! {
151+
v = tx => v,
152+
v = rx => v,
153+
}
154+
})
101155
})??
102156
};
103157
if !self.non_interactive {

sw/host/tests/chip/jtag/src/openocd_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn test_openocd(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
4242
const CONSOLE_TIMEOUT: Duration = Duration::from_secs(5);
4343

4444
let mut console = UartConsole::new(Some(CONSOLE_TIMEOUT), Some(Regex::new(r"PASS!")?), None);
45-
let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
45+
let result = console.interact(&*uart, Some(&mut std::io::stdout()))?;
4646
log::info!("result: {:?}", result);
4747

4848
//

sw/host/tests/chip/jtag/src/sram_load.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn test_sram_load(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
5454
)?),
5555
None,
5656
);
57-
let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
57+
let result = console.interact(&*uart, Some(&mut std::io::stdout()))?;
5858
log::info!("result: {:?}", result);
5959
jtag.halt()?;
6060
jtag.disconnect()?;

sw/host/tests/chip/power_virus/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn power_virus_systemtest(opts: &Opts, transport: &TransportWrapper) -> Result<(
3232
Some(Regex::new(r"(FAIL|FAULT).*\n")?),
3333
);
3434
let mut stdout = std::io::stdout();
35-
let result = console.interact(&*uart, None, Some(&mut stdout))?;
35+
let result = console.interact(&*uart, Some(&mut stdout))?;
3636
match result {
3737
ExitStatus::None | ExitStatus::CtrlC => Ok(()),
3838
ExitStatus::Timeout => Err(anyhow!("Console timeout exceeded")),

sw/host/tests/chip/rv_core_ibex_epmp/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fn ibex_epmp_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
7070
);
7171

7272
let mut stdout = std::io::stdout();
73-
let result = console.interact(&*uart, None, Some(&mut stdout))?;
73+
let result = console.interact(&*uart, Some(&mut stdout))?;
7474
match result {
7575
ExitStatus::None | ExitStatus::CtrlC => Ok(()),
7676
ExitStatus::Timeout => Err(anyhow!("Console timeout exceeded")),

sw/host/tests/chip/spi_device/src/spi_device_flash_smoketest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn main() -> Result<()> {
9393
);
9494

9595
// Now watch the console for the exit conditions.
96-
let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
96+
let result = console.interact(&*uart, Some(&mut std::io::stdout()))?;
9797
if result != ExitStatus::ExitSuccess {
9898
bail!("FAIL: {:?}", result);
9999
};

sw/host/tests/chip/spi_device/src/spi_device_sleep_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fn main() -> Result<()> {
104104
);
105105

106106
// Now watch the console for the exit conditions.
107-
let result = console.interact(&*uart, None, Some(&mut std::io::stdout()))?;
107+
let result = console.interact(&*uart, Some(&mut std::io::stdout()))?;
108108
if result != ExitStatus::ExitSuccess {
109109
bail!("FAIL: {:?}", result);
110110
};

0 commit comments

Comments
 (0)