use libc::{
cfsetspeed, tcgetattr, tcsetattr, termios, B38400, CLOCAL, CREAD, CRTSCTS, CS8, CSIZE, CSTOPB,
ECHO, ISIG, IXANY, IXOFF, IXON, OCRNL, ONLCR, OPOST, PARENB, TCSANOW, VMIN, VTIME,
};
use std::io::Error;
use std::os::unix::io::AsRawFd;
use std::path::Path;
#[derive(Debug)]
pub struct Port {
file: std::fs::File,
}
impl Port {
pub fn open<P: AsRef<Path>>(device: P) -> Result<Self, Error> {
let file = std::fs::File::options()
.read(true)
.write(true)
.open(device)?;
unsafe {
let fd = file.as_raw_fd();
let mut tty: termios = std::mem::zeroed();
if tcgetattr(fd, &mut tty as *mut _) != 0 {
return Err(Error::last_os_error());
}
if cfsetspeed(&mut tty as *mut _, B38400) != 0 {
return Err(Error::last_os_error());
}
tty.c_cflag = (tty.c_cflag & !CSIZE) | CS8; tty.c_cflag &= !PARENB; tty.c_cflag &= !CSTOPB;
tty.c_cflag &= !CRTSCTS; tty.c_iflag &= !(IXON | IXOFF | IXANY); tty.c_cflag |= CLOCAL; tty.c_cflag |= CREAD; tty.c_lflag &= !ECHO; tty.c_lflag &= !ISIG; tty.c_oflag &= !OPOST; tty.c_oflag &= !(ONLCR | OCRNL);
tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0;
if tcsetattr(fd, TCSANOW, &tty as *const _) != 0 {
return Err(Error::last_os_error());
}
}
Ok(Self { file })
}
}
impl std::io::Read for Port {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.file.read(buf)
}
}
impl std::io::Write for Port {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.file.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.file.flush()
}
}