I am attempting to communicate with a serial device over a TTL->RS-232 converter. This converter requires power be sent on the DTR and RTS lines.
// imports
extern crate serial; //see: https://dcuddeback.github.io/serial-rs/serial/index.html
use std::env;
use std::io;
use std::time::Duration;
use std::process::exit;
use std::io::prelude::*;
use serial::prelude::*;
use serial::{BaudRate, CharSize, Parity, StopBits, FlowControl, SystemPort, PortSettings, Error};
use std::mem;
#[inline]
fn display_error_message(err: &Error, msg: &str) -> ! {
println!("{}", msg);
println!("Error Code: {:?}", err.raw_os_error());
println!("Error: {:?}", err);
exit(0);
}
fn main() {
// open port
let mut port = match serial::open("COM3") {
Err(ref e) => display_error_message(e, "Error opening serial port"),
Ok(x) => x,
};
// push settings to stack
let settings = PortSettings {
baud_rate: BaudRate::Baud115200,
char_size: CharSize::Bits8,
parity: Parity::ParityNone,
stop_bits: StopBits::Stop1,
flow_control: FlowControl::FlowNone,
};
// configure port
match port.configure(&settings) {
Ok(_) => {}
Err(ref e) => display_error_message(e, "Error configuring serial port."),
};
// set rts
match port.set_rts(true) {
Ok(_) => {}
Err(ref e) => display_error_message(e, "Error setting RTS line"),
};
// set DTR
match port.set_dtr(true) {
Ok(_) => {}
Err(ref e) => display_error_message(e, "Error setting DTR line"),
};
// allocate readbuffer on stack
let mut rb: [u8; 1] = [0u8; 1];
// allocate buffer to hold output
let mut out: String = String::with_capacity(1024);
// loop while reading
loop {
match port.read(&mut rb) {
Ok(_) => {}
Err(ref e) => {
println!("Error reading serial port.");
println!("Error: {:?}", e);
exit(0);
}
};
match rb[0] {
// Linefeed
10 => {
println!("{}<LF>", &out);
out = String::with_capacity(1024);
}
// carriage return
13 => {
println!("{}<CR>", &out);
out = String::with_capacity(1024);
}
// normal chars
32...126 => {
let temp: u32 = rb[0].clone() as u32;
let ch: char = unsafe { mem::transmute(temp) };
out.push(ch);
}
// everything else
x => {
println!("Non standard character encountered");
println!("Value: {:?}", x);
exit(0);
}
};
}
}
The source code is also on the Rust Playground and Github.
I am using the serial-rs library and Rust 1.8 (GNU ABI Windows 7 x64 Professional).
My error occurs on line 46:
match port.set_dtr( true ) {
Ok(_) => { },
Err(ref e) => display_error_message(e,"Error setting DTR line")
};
This returns error code 87 (on Windows 7). The standard serial-rs doesn't save the error code so I'm using my own fork (pending a PR).
This error is from a malformed system call. Diving into serial-rs one will see set_dtr(bool)
is just wrapping a call to EscapeCommFunction(2) first call, second call, third call. The arguments codes appear correct.
Compiling with the MSVC toolchain results in same error, placing the DTR call before RTS call results in same error.
Raising DTR and RTS at the same time works in py-serial, but I can't write to the port while doing so. See other issue