Skip to content
This repository has been archived by the owner on Apr 10, 2024. It is now read-only.

Commit

Permalink
Added serial/modem support.
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrueger committed Feb 27, 2024
1 parent 0c93f7a commit 683e0ae
Show file tree
Hide file tree
Showing 15 changed files with 239 additions and 21 deletions.
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "icy_term"
version = "0.7.3"
version = "0.8.0"
edition = "2021"
authors = ["Mike Krüger <[email protected]>"]
description = "A terminal program supporting CP437, PetScii and ViewData"
Expand All @@ -19,14 +19,15 @@ egui_extras = { version="0.26.0", features = ["all_loaders"] }
egui_glow = "0.26.0"
egui-modal = "0.3.3"
egui-bind = "0.11.0"
egui_file = "0.15.0"
egui_file = "0.16.2"
glow = "0.13.0"
dark-light = "1.0.0"
serde = "1.0.185"
versions = "6.1.0"
regex = "1.5.4"
github_release_check = "0.2.1"
semver = "1.0.20"
serial = "0.4.0"

#sound
rodio = { version = "0.17.1" , default-features = false, features = [] }
Expand All @@ -53,7 +54,7 @@ once_cell = "1.18.0"

log = "0.4"
log4rs = "1.2.0"
web-time = "0.2.0"
web-time = "1.0.0"

# WebSocket support
tungstenite = { version = "0.21.0", features = [
Expand Down
2 changes: 2 additions & 0 deletions i18n/de/icy_term.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ settings-keybinds-download = Download:
settings-keybinds-quit = Beenden:
settings-keybinds-show-find = Suchen:
settings-modem-category = Modem
dialing_directory-connect-to = Verbinde zu…
dialing_directory-new_bbs = Neue BBS
dialing_directory-name-placeholder = BBS Name
Expand Down
7 changes: 7 additions & 0 deletions i18n/en/icy_term.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ settings-keybinds-download = Download:
settings-keybinds-quit = Quit:
settings-keybinds-show-find = Find:
settings-modem-category = Modem
settings-modem-device = Device:
settings-modem-baud_rate = Baudrate:
settings-modem-data_bits = Databits/ Stopbits / Parity:
settings-modem-init_string = Init string:
settings-modem_dial_string = Dial string:
dialing_directory-connect-to = Quick connect to…
dialing_directory-new_bbs = New BBS
dialing_directory-name-placeholder = BBS name
Expand Down
5 changes: 4 additions & 1 deletion src/com/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ pub use telnet::*;
pub mod raw;
pub use raw::*;

pub mod modem;
pub use modem::*;

pub mod websocket;

#[cfg(not(target_arch = "wasm32"))]
Expand All @@ -19,7 +22,7 @@ pub mod ssh;
use crate::{addresses::Terminal, ui::connect::OpenConnectionData};
pub type TermComResult<T> = Result<T, Box<dyn Error + Send + Sync>>;

pub trait Com: Sync + Send {
pub trait Com {
fn get_name(&self) -> &'static str;
fn default_port(&self) -> u16;

Expand Down
66 changes: 66 additions & 0 deletions src/com/modem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#![allow(dead_code)]

use crate::Modem;

use super::{Com, OpenConnectionData, TermComResult};
use dark_light::Mode;
use serial::{prelude::*, unix::TTYPort};
use std::{
io::{self, ErrorKind, Read, Write},
net::{TcpStream, ToSocketAddrs},
time::Duration,
};

pub struct ComModemImpl {
modem: Modem,
port: Box<dyn serial::SerialPort>,
}

impl ComModemImpl {
pub fn connect(connection_data: &OpenConnectionData) -> TermComResult<Self> {
let modem = connection_data.modem.as_ref().unwrap().clone();
let mut port = serial::open(&modem.device)?;
port.reconfigure(&|settings| {
settings.set_baud_rate(serial::BaudRate::from_speed(modem.baud_rate))?;
settings.set_char_size(modem.char_size);
settings.set_parity(modem.parity);
settings.set_stop_bits(modem.stop_bits);
settings.set_flow_control(modem.flow_control);
Ok(())
})?;
port.write_all(modem.init_string.as_bytes())?;
port.write_all(b"\n")?;
port.write_all(modem.dial_string.as_bytes())?;
port.write_all(connection_data.address.as_bytes())?;
port.write_all(b"\n")?;
Ok(Self { modem, port: Box::new(port) })
}
}

impl Com for ComModemImpl {
fn get_name(&self) -> &'static str {
"Modem"
}

fn default_port(&self) -> u16 {
0
}

fn set_terminal_type(&mut self, _terminal: crate::addresses::Terminal) {}

fn read_data(&mut self) -> TermComResult<Option<Vec<u8>>> {
let mut buf: Vec<u8> = (0..255).collect();
let size = self.port.read(&mut buf[..])?;
buf.truncate(size);
Ok(Some(buf))
}

fn send(&mut self, buf: &[u8]) -> TermComResult<usize> {
self.port.write_all(buf)?;
Ok(buf.len())
}

fn disconnect(&mut self) -> TermComResult<()> {
Ok(())
}
}
6 changes: 4 additions & 2 deletions src/data/addresses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::TerminalResult;
use chrono::{Duration, Utc};
use icy_engine::ansi::{BaudEmulation, MusicOption};
use icy_engine::igs::CommandExecutor;
use icy_engine::{ansi, ascii, atascii, avatar, petscii, rip, viewdata, mode7, BufferParser, UnicodeConverter};
use icy_engine::{ansi, ascii, atascii, avatar, mode7, petscii, rip, viewdata, BufferParser, UnicodeConverter};
use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
use regex::Regex;
use std::fs::File;
Expand Down Expand Up @@ -108,6 +108,7 @@ pub enum Protocol {
#[default]
Telnet,
Raw,
Modem,
Ssh,
WebSocket(bool), // true=secure
}
Expand All @@ -127,9 +128,10 @@ impl Display for Protocol {

impl Protocol {
#[cfg(not(target_arch = "wasm32"))]
pub const ALL: [Protocol; 5] = [
pub const ALL: [Protocol; 6] = [
Protocol::Telnet,
Protocol::Raw,
Protocol::Modem,
Protocol::Ssh,
Protocol::WebSocket(true),
Protocol::WebSocket(false),
Expand Down
3 changes: 3 additions & 0 deletions src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ pub use options::*;

pub mod addresses;
pub use addresses::*;

pub mod modem;
pub use modem::*;
34 changes: 34 additions & 0 deletions src/data/modem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use serial::{prelude::*, CharSize, FlowControl, StopBits};

#[derive(Clone, Debug, PartialEq)]
pub struct Modem {
pub device: String,
pub baud_rate: usize,

pub char_size: CharSize,
pub stop_bits: StopBits,
pub parity: serial::Parity,

pub flow_control: FlowControl,

pub init_string: String,
pub dial_string: String,
}

impl Default for Modem {
fn default() -> Self {
Self {
#[cfg(target_os = "windows")]
device: "COM1".to_string(),
#[cfg(not(target_os = "windows"))]
device: "/dev/ttyS0".to_string(),
baud_rate: 9600,
char_size: CharSize::Bits8,
stop_bits: StopBits::Stop1,
parity: serial::Parity::ParityNone,
flow_control: FlowControl::FlowNone,
init_string: "ATZ".to_string(),
dial_string: "ATDT".to_string(),
}
}
}
5 changes: 4 additions & 1 deletion src/data/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use icy_engine::Color;
use icy_engine_egui::MonitorSettings;
use toml::Value;

use crate::TerminalResult;
use crate::{Modem, TerminalResult};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Scaling {
Expand Down Expand Up @@ -276,6 +276,8 @@ pub struct Options {
pub monitor_settings: MonitorSettings,
pub bind: KeyBindings,
pub iemsi: IEMSISettings,

pub modem: Modem,
}

impl Default for Options {
Expand All @@ -288,6 +290,7 @@ impl Default for Options {
console_beep: true,
bind: KeyBindings::default(),
is_dark_mode: None,
modem: Modem::default(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/ui/com_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl ConnectionThreadData {
self.com = match connection_data.protocol {
crate::addresses::Protocol::Telnet => Box::new(crate::com::ComTelnetImpl::connect(connection_data)?),
crate::addresses::Protocol::Raw => Box::new(crate::com::ComRawImpl::connect(connection_data)?),
crate::addresses::Protocol::Modem => Box::new(crate::com::ComModemImpl::connect(connection_data)?),
#[cfg(not(target_arch = "wasm32"))]
crate::addresses::Protocol::Ssh => Box::new(crate::com::ssh::SSHComImpl::connect(connection_data)?),
crate::addresses::Protocol::WebSocket(_) => {
Expand Down
10 changes: 6 additions & 4 deletions src/ui/connect.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Address, Terminal, TerminalResult};
use crate::{Address, Modem, Terminal, TerminalResult};
use std::{collections::VecDeque, sync::mpsc};
use web_time::{Duration, Instant};

Expand Down Expand Up @@ -163,9 +163,9 @@ impl Connection {
Ok(())
}

pub fn connect(&self, call_adr: &Address, timeout: Duration, window_size: icy_engine::Size) -> TerminalResult<()> {
pub fn connect(&self, call_adr: &Address, timeout: Duration, window_size: icy_engine::Size, modem: Option<Modem>) -> TerminalResult<()> {
self.tx
.send(SendData::OpenConnection(OpenConnectionData::from(call_adr, timeout, window_size)))?;
.send(SendData::OpenConnection(OpenConnectionData::from(call_adr, timeout, window_size, modem)))?;
Ok(())
}
}
Expand All @@ -181,10 +181,11 @@ pub struct OpenConnectionData {
pub protocol: crate::Protocol,
pub timeout: Duration,
pub window_size: icy_engine::Size,
pub modem: Option<Modem>,
}

impl OpenConnectionData {
pub fn from(call_adr: &Address, timeout: Duration, window_size: icy_engine::Size) -> Self {
pub fn from(call_adr: &Address, timeout: Duration, window_size: icy_engine::Size, modem: Option<Modem>) -> Self {
Self {
address: call_adr.address.clone(),
user_name: call_adr.user_name.clone(),
Expand All @@ -193,6 +194,7 @@ impl OpenConnectionData {
protocol: call_adr.protocol,
timeout,
window_size,
modem,
}
}
}
Expand Down
Loading

0 comments on commit 683e0ae

Please sign in to comment.