diff --git a/Cargo.toml b/Cargo.toml index a92ff6c..0f219d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,20 @@ [package] -authors = ["Marc Brinkmann "] +authors = ["Marc Brinkmann , MichaƂ Hanusek "] name = "rs485" -version = "0.1.0" +version = "0.1.1" description = "RS485 serial support (Linux)" license = "MIT" repository = "https://github.com/mbr/rs485-rs" documentation = "https://docs.rs/rs485" +edition = "2018" [dependencies] -bitflags = "0.9.1" libc = "0.2.24" + +[[example]] +name = "echo" +crate-type = ["bin"] + +[dev-dependencies] +serialport = "3.3.0" +hex-slice = "0.1.4" diff --git a/examples/echo.rs b/examples/echo.rs new file mode 100644 index 0000000..af593e2 --- /dev/null +++ b/examples/echo.rs @@ -0,0 +1,85 @@ +use std::env; +use std::path::Path; +use std::io::{Read, Write}; +use std::os::unix::io::AsRawFd; +use serialport::posix::TTYPort; +use serialport::{SerialPortSettings, FlowControl, Parity, DataBits, StopBits}; +use rs485::SerialRs485; +use hex_slice::AsHex; + +const NAME: &'static str = env!("CARGO_PKG_NAME"); +const DEFAULT_SERIALPORT: &'static str = "/dev/ttyO4"; + +fn help() { + println!("usage: ./{} [serial-port]\n for example : ./{} {}\n \ + Serial port settings: 115200 8N1", NAME, NAME, DEFAULT_SERIALPORT); + std::process::exit(0); +} + +fn main() { + println!("RS 485 Echo Example"); + let args: Vec = env::args().collect(); + + let mut port_name = String::new(); + match args.len() { + 2 => { + port_name = args[1].to_string(); + }, + _ => { help(); } + }; + + let mut settings: SerialPortSettings = Default::default(); + settings.baud_rate = 115200; + settings.flow_control = FlowControl::None; + settings.parity = Parity::None; + settings.data_bits = DataBits::Eight; + settings.stop_bits = StopBits::One; + + let path = Path::new(&port_name); + + let mut port; + match TTYPort::open(&path, &settings) + { + Ok(r) => { + port = r; + println!("Successfully Opened : {}", port_name); + }, + Err(_) => { + println!("Error. Failed connect to open serial port : {}", port_name.to_string()); + std::process::exit(1); + } + } + + let fd = port.as_raw_fd(); + println!("fd : {}", fd); + + let mut rs485ctl = SerialRs485::default(); + + rs485ctl.set_rts_on_send(false); + rs485ctl.set_rts_after_send(true); + + rs485ctl.set_on_fd(fd).unwrap(); + + println!("Press CTRL+C to exit"); + + let mut serial_data = [0 as u8; 32]; + + loop + { + match port.read(&mut serial_data) + { + Ok(size) => { + println!("Read bytes : {:02X} text : {:?}", serial_data[..size].as_hex(), String::from_utf8_lossy(&serial_data[..size])); + if size != 0 { + let wr = port.write(&serial_data[..size]).expect("Failed to write to serial port"); + println!("Write result : {:?}", wr); + } + }, + Err(e) => { + if e.kind() == std::io::ErrorKind::TimedOut { continue; } + println!("Error. Failed read. serial-port : {}. Error : {}", port_name.to_string(), e); + }, + }; + } +} + diff --git a/src/lib.rs b/src/lib.rs index d309530..480e577 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,10 +37,6 @@ //! is actually connected to the transceiver, properly pinmuxed (if necessary) //! and that the UART itself is enabled. -#[macro_use] -extern crate bitflags; -extern crate libc; - use libc::c_ulong; use std::{mem, io}; use std::os::unix::io::{AsRawFd, RawFd}; @@ -49,14 +45,16 @@ use std::os::unix::io::{AsRawFd, RawFd}; const TIOCSRS485: c_ulong = 0x542f; const TIOCGRS485: c_ulong = 0x542e; -// bitflags used by rs485 functionality -bitflags! { - pub struct Rs485Flags: u32 { - const SER_RS485_ENABLED = (1 << 0); - const SER_RS485_RTS_ON_SEND = (1 << 1); - const SER_RS485_RTS_AFTER_SEND = (1 << 2); - const SER_RS485_RX_DURING_TX = (1 << 4); - } +#[derive(Copy, Clone, Debug)] +pub struct Rs485Flags { + bits: u32, +} + +impl Rs485Flags { + pub const SER_RS485_ENABLED: Self = Rs485Flags { bits: (1 << 0) }; + pub const SER_RS485_RTS_ON_SEND: Self = Rs485Flags { bits: (1 << 1) }; + pub const SER_RS485_RTS_AFTER_SEND: Self = Rs485Flags { bits: (1 << 2) }; + pub const SER_RS485_RX_DURING_TX: Self = Rs485Flags { bits: (1 << 4) }; } #[repr(C)] @@ -81,6 +79,16 @@ impl SerialRs485 { unsafe { mem::zeroed() } } + #[inline] + pub fn default() -> SerialRs485 { + SerialRs485{ + flags : Rs485Flags::SER_RS485_ENABLED, + delay_rts_before_send : 0, + delay_rts_after_send : 0, + _padding : [0u32; 5] + } + } + /// Load settings from file descriptor /// /// Settings will be loaded from the file descriptor, which must be a @@ -96,7 +104,6 @@ impl SerialRs485 { } Ok(conf) - } /// Enable RS485 support @@ -105,9 +112,9 @@ impl SerialRs485 { #[inline] pub fn set_enabled<'a>(&'a mut self, enabled: bool) -> &'a mut Self { if enabled { - self.flags |= SER_RS485_ENABLED; + self.flags.bits |= Rs485Flags::SER_RS485_ENABLED.bits; } else { - self.flags &= !SER_RS485_ENABLED; + self.flags.bits &= !Rs485Flags::SER_RS485_ENABLED.bits; } self @@ -120,9 +127,9 @@ impl SerialRs485 { #[inline] pub fn set_rts_on_send<'a>(&'a mut self, rts_on_send: bool) -> &'a mut Self { if rts_on_send { - self.flags |= SER_RS485_RTS_ON_SEND; + self.flags.bits |= Rs485Flags::SER_RS485_RTS_ON_SEND.bits; } else { - self.flags &= !SER_RS485_RTS_ON_SEND; + self.flags.bits &= !Rs485Flags::SER_RS485_RTS_ON_SEND.bits; } self @@ -135,9 +142,9 @@ impl SerialRs485 { #[inline] pub fn set_rts_after_send<'a>(&'a mut self, rts_after_send: bool) -> &'a mut Self { if rts_after_send { - self.flags |= SER_RS485_RTS_AFTER_SEND; + self.flags.bits |= Rs485Flags::SER_RS485_RTS_AFTER_SEND.bits; } else { - self.flags &= !SER_RS485_RTS_AFTER_SEND; + self.flags.bits &= !Rs485Flags::SER_RS485_RTS_AFTER_SEND.bits; } self @@ -170,9 +177,9 @@ impl SerialRs485 { /// even when using half-duplex. pub fn set_rx_during_tx<'a>(&'a mut self, set_rx_during_tx: bool) -> &'a mut Self { if set_rx_during_tx { - self.flags |= SER_RS485_RX_DURING_TX + self.flags.bits |= Rs485Flags::SER_RS485_RX_DURING_TX.bits; } else { - self.flags &= !SER_RS485_RX_DURING_TX; + self.flags.bits &= !Rs485Flags::SER_RS485_RX_DURING_TX.bits; } self }