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 { 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 { 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) } } } } } }