From 3ffc78fa0dc1d58619894129cda4ae3c1acf8eb6 Mon Sep 17 00:00:00 2001 From: rincewound Date: Tue, 10 Dec 2024 20:27:55 +0100 Subject: [PATCH] Improve robustness in case of bad settings --- src/analyzer_mode.rs | 5 +++++ src/main.rs | 14 ++++++++++---- src/portthread.rs | 6 ++++++ src/settings_mode.rs | 32 ++++++++++++++++++++------------ 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/analyzer_mode.rs b/src/analyzer_mode.rs index 9eb8aee..50afd31 100644 --- a/src/analyzer_mode.rs +++ b/src/analyzer_mode.rs @@ -54,6 +54,11 @@ impl AnalyzerMode { active_display_mode: DisplayMode::Hex, } } + + pub(crate) fn add_to_history(&mut self, arg: &str) { + let msg = SerialStateMessage::ErrorEvent(arg.to_string()); + self.display_history.push(msg); + } } impl ApplicationMode for AnalyzerMode { diff --git a/src/main.rs b/src/main.rs index e828460..303d441 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,6 +75,7 @@ impl Default for App { let (stx, rtx): (Sender, Receiver) = mpsc::channel(); let (tx, rx): (Sender, Receiver) = mpsc::channel(); + let settings = settings_mode::SettingsMode::new(); portthread::port_background_thread(rx, stx); let data = App { @@ -82,7 +83,7 @@ impl Default for App { exit: false, command_sender: tx.clone(), state_receiver: rtx, - settingsmode: settings_mode::SettingsMode::new(), + settingsmode: settings, analyzermode: analyzer_mode::AnalyzerMode::new(), interactivemode: interactive_mode::InteractiveMode::new(tx), }; @@ -241,9 +242,14 @@ impl App { /// This function will panic if there is a failure in opening the serial port or setting /// the read/write timeouts. fn enter_interactive_mode(&mut self) { - let ctx = self.settingsmode.create_serial_context(); - self.send_command(SerialCommand::Start(ctx)); - self.enable_mode(mode::Mode::Interactive); + if let Ok(ctx) = self.settingsmode.create_serial_context() { + self.send_command(SerialCommand::Stop); + self.send_command(SerialCommand::Start(ctx)); + self.enable_mode(mode::Mode::Interactive); + } else { + self.analyzermode + .add_to_history("Failed to open serial port"); + } } /// Exits the current mode and enters the settings mode, which is a mode where the user can adjust diff --git a/src/portthread.rs b/src/portthread.rs index 69937e8..0691e31 100644 --- a/src/portthread.rs +++ b/src/portthread.rs @@ -4,6 +4,12 @@ use std::{ thread, vec, }; +pub enum PortError { + BadSettings, + FailedToFlush, + FailedToOpen, +} + #[derive(Debug)] pub struct SerialContext { port_name: String, diff --git a/src/settings_mode.rs b/src/settings_mode.rs index de7df80..9576b39 100644 --- a/src/settings_mode.rs +++ b/src/settings_mode.rs @@ -10,7 +10,7 @@ use ratatui::{ use crate::{ mode::ApplicationMode, - portthread::SerialContext, + portthread::{PortError, SerialContext}, serialtypes::{BAUD_RATES, DATABITS, PARITY, STOP_BITS}, DisplayMode, DISPLAY_MODES, }; @@ -35,7 +35,6 @@ impl ApplicationMode for SettingsMode { KeyCode::Char('a') => self.rotate_parity(), KeyCode::Char('d') => self.rotate_databits(), KeyCode::Char('m') => self.rotate_display_mode(), - //KeyCode::Enter => app.enter_interactive_mode(), _ => {} } } @@ -98,7 +97,7 @@ impl SettingsMode { self.display_mode } - pub fn create_serial_context(&self) -> SerialContext { + pub fn create_serial_context(&self) -> Result { let the_port = serial2::SerialPort::open(&self.port, |mut settings: serial2::Settings| { let _ = settings.set_baud_rate(self.baud); let stop_bits = match self.stopbits { @@ -137,15 +136,24 @@ impl SettingsMode { Ok(settings) }); - let mut p = the_port.expect("Failed to open port with given settings."); - p.set_read_timeout(Duration::from_millis(125)) - .expect("Failed to set read timeout."); - p.set_write_timeout(Duration::from_millis(2500)) - .expect("Failed to set write timeout."); - p.flush().expect("Failed to flush port."); - let _ = p.discard_buffers(); - let ctx = SerialContext::new(self.port.clone(), p); - ctx + if let Ok(mut p) = the_port { + if let Err(_) = p.set_read_timeout(Duration::from_millis(125)) { + return Err(PortError::BadSettings); + } + if let Err(_) = p.set_write_timeout(Duration::from_millis(2500)) { + return Err(PortError::BadSettings); + } + if let Err(_) = p.flush() { + return Err(PortError::FailedToFlush); + } + if let Err(_) = p.discard_buffers() { + return Err(PortError::BadSettings); + } + + return Ok(SerialContext::new(self.port.clone(), p)); + } else { + return Err(PortError::FailedToOpen); + } } /// Rotates the serial port to the next available serial port.