113 lines
2.5 KiB
Rust
113 lines
2.5 KiB
Rust
use std::io::{Error, ErrorKind, Write};
|
|
use std::time::Duration;
|
|
|
|
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
|
use serial2::SerialPort;
|
|
|
|
struct RawMode {}
|
|
|
|
impl RawMode {
|
|
fn init() -> Result<Self, Error> {
|
|
crossterm::terminal::enable_raw_mode()?;
|
|
Ok(Self {})
|
|
}
|
|
}
|
|
|
|
impl Drop for RawMode {
|
|
fn drop(&mut self) {
|
|
let _ = crossterm::terminal::disable_raw_mode();
|
|
}
|
|
}
|
|
|
|
|
|
pub struct Monitor {
|
|
hooks: Vec<(KeyCode, KeyModifiers, &'static str)>
|
|
}
|
|
|
|
impl Monitor {
|
|
pub fn new() -> Self {
|
|
let mut hooks = Vec::new();
|
|
|
|
hooks.push((KeyCode::Char('c'), KeyModifiers::CONTROL, "Exit monitor"));
|
|
hooks.push((KeyCode::Char('r'), KeyModifiers::CONTROL, "Reboot target"));
|
|
|
|
Self { hooks }
|
|
}
|
|
|
|
pub fn add_hook(&mut self, key: KeyCode, mods: KeyModifiers, desc: &'static str) -> usize {
|
|
let idx = self.hooks.len();
|
|
self.hooks.push((key, mods, desc));
|
|
idx
|
|
}
|
|
|
|
pub fn run(&mut self, port: &mut SerialPort) -> Result<usize, Error> {
|
|
port.set_dtr(true)?;
|
|
port.set_rts(true)?;
|
|
std::thread::sleep(Duration::from_millis(100));
|
|
port.set_dtr(false)?;
|
|
port.set_rts(false)?;
|
|
|
|
println!();
|
|
println!("Monitor controls:");
|
|
|
|
for (key, mods, desc) in &self.hooks {
|
|
let key = match (key, *mods) {
|
|
(KeyCode::Char(c), KeyModifiers::NONE) => format!("{}", c.to_uppercase()),
|
|
(KeyCode::Char(c), KeyModifiers::CONTROL) => format!("Ctrl+{}", c.to_uppercase()),
|
|
key => format!("{:?}", key)
|
|
};
|
|
|
|
println!(" {} - {}", key, desc);
|
|
}
|
|
|
|
println!();
|
|
|
|
let _raw = RawMode::init()?;
|
|
let mut stdout = std::io::stdout();
|
|
|
|
'main: loop {
|
|
let mut buf = [0u8; 1];
|
|
|
|
let res = port.read_exact(&mut buf);
|
|
|
|
if res.is_ok() {
|
|
if buf[0] == b'\n' {
|
|
stdout.write_all(b"\r")?;
|
|
}
|
|
|
|
stdout.write_all(&buf)?;
|
|
stdout.flush()?;
|
|
}
|
|
|
|
if let Err(err) = res && err.kind() != ErrorKind::TimedOut {
|
|
Err(err)?
|
|
}
|
|
|
|
if crossterm::event::poll(Duration::ZERO)? {
|
|
let (key, mods) = match crossterm::event::read()? {
|
|
Event::Key(ev) => (ev.code, ev.modifiers),
|
|
_ => continue
|
|
};
|
|
|
|
if key == KeyCode::Char('r') && mods == KeyModifiers::CONTROL {
|
|
stdout.write_all(b"\r\n*** Reboot ***\r\n")?;
|
|
port.set_dtr(true)?;
|
|
port.set_rts(true)?;
|
|
std::thread::sleep(Duration::from_millis(10));
|
|
port.set_dtr(false)?;
|
|
port.set_rts(false)?;
|
|
continue
|
|
}
|
|
|
|
for (idx, (hook_key, hook_mods, _)) in self.hooks.iter().enumerate() {
|
|
if hook_key == &key && hook_mods == &mods {
|
|
stdout.write_all(b"\r\n")?;
|
|
break 'main Ok(idx)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|