Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ name = "lw-lwnx"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = []

[dependencies]
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["impl-default", "ioapiset"] }
# winapi = "0.3.9"

[target.'cfg(unix)'.dependencies]
serialport = "4"
61 changes: 61 additions & 0 deletions src/linux_serialport.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::{io::{Read, Write}, time::Duration};
use serialport::{self, DataBits, FlowControl, Parity, SerialPort, StopBits};

#[derive(Debug)]
pub enum LinuxSerialPortError {
InvalidSerialPort,
OpenFailed,
WriteFailed,
DidNotWriteAllBytes,
ReadFailed,
}

impl From<LinuxSerialPortError> for String {
fn from(v: LinuxSerialPortError) -> Self { format!("{v:?}") }
}

pub struct LinuxSerialPort {
port: Option<Box<dyn SerialPort>>,
}

impl LinuxSerialPort {
pub fn new() -> Self { Self { port: None } }
pub fn is_invalid(&self) -> bool { self.port.is_none() }

pub fn connect(&mut self, path: &str, bit_rate: u32) -> Result<(), String> {
let p = serialport::new(path, bit_rate)
.data_bits(DataBits::Eight)
.parity(Parity::None)
.stop_bits(StopBits::One)
.flow_control(FlowControl::None)
.timeout(Duration::from_millis(10))
.open()
.map_err(|_| String::from(LinuxSerialPortError::OpenFailed))?;
self.port = Some(p);
Ok(())
}

pub fn disconnect(&mut self) { self.port = None; }

pub fn write(&mut self, buffer: &[u8]) -> Result<u32, LinuxSerialPortError> {
let p = self.port.as_mut().ok_or(LinuxSerialPortError::InvalidSerialPort)?;
let mut total = 0;
while total < buffer.len() {
match p.write(&buffer[total..]) {
Ok(n) if n > 0 => total += n,
Ok(_) => return Err(LinuxSerialPortError::WriteFailed),
Err(_) => return Err(LinuxSerialPortError::WriteFailed),
}
}
if total != buffer.len() { return Err(LinuxSerialPortError::DidNotWriteAllBytes); }
Ok(total as u32)
}

pub fn read<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], LinuxSerialPortError> {
let p = self.port.as_mut().ok_or(LinuxSerialPortError::InvalidSerialPort)?;
match p.read(buf) {
Ok(n) => Ok(&buf[..n]),
Err(_) => Err(LinuxSerialPortError::ReadFailed),
}
}
}
30 changes: 21 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use std::{thread, time::Duration};

use std::sync::WaitTimeoutResult;
use serialport::{available_ports, SerialPort, SerialPortType};
use win32_serialport::WinSerialPort;

mod lwnx;

#[cfg(windows)]
mod win32_serialport;
#[cfg(windows)]
use win32_serialport::WinSerialPort as SerialPort;

#[cfg(unix)]
mod linux_serialport;
#[cfg(unix)]
use linux_serialport::LinuxSerialPort as MySerialPort;

/// Implementation example for the Rust serialport crate.
impl lwnx::UserPlatform for Box<dyn SerialPort> {
Expand All @@ -28,7 +36,7 @@ impl lwnx::UserPlatform for Box<dyn SerialPort> {
}

/// Implementation example for the LightWare serial port implementation.
impl lwnx::UserPlatform for &WinSerialPort {
impl lwnx::UserPlatform for MySerialPort {
fn write_callback(&mut self, data: &[u8]) -> Result<usize, lwnx::LwnxError> {
match self.write(data) {
Ok(bytes_written) => Ok(bytes_written as usize),
Expand All @@ -50,11 +58,11 @@ impl lwnx::UserPlatform for &WinSerialPort {

/// Implementation example for a user struct that references a serial port.
struct MyPlatform<'a> {
port: &'a WinSerialPort,
port: &'a mut MySerialPort,
trace_packet: bool,
}

impl lwnx::UserPlatform for &MyPlatform<'_> {
impl lwnx::UserPlatform for MyPlatform<'_> {
fn write_callback(&mut self, data: &[u8]) -> Result<usize, lwnx::LwnxError> {
if self.trace_packet {
println!("Writing bytes: {:X?}", data);
Expand Down Expand Up @@ -99,15 +107,19 @@ fn main() -> Result<(), String> {
};
}

let mut port = WinSerialPort::new();
let mut port = MySerialPort::new();

#[cfg(windows)]
port.connect("COM5", 921600)?;
// let mut device_context = lwnx::DeviceContext::new(&port);

#[cfg(unix)]
port.connect("/dev/ttyACM0", 921600)?;

let my_platform = MyPlatform {
port: &port,
port: &mut port,
trace_packet: true,
};
let mut device_context = lwnx::DeviceContext::new(&my_platform);
let mut device_context = lwnx::DeviceContext::new(my_platform);

// let mut port = serialport::new("COM5", 921600)
// .timeout(Duration::from_millis(1))
Expand Down