Use rust serial crate for reading from serial
Incomplete - can successfully initiate contact w/ radio but can't read data
This commit is contained in:
parent
963dc072c9
commit
c56fa32b2c
@ -13,6 +13,7 @@ crate-type = ["staticlib"]
|
|||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
getopts = "0.2"
|
getopts = "0.2"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
serial = "0.4"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.53.1"
|
bindgen = "0.53.1"
|
||||||
|
@ -44,8 +44,6 @@ extern {
|
|||||||
fn hid_init(vid: c_int, pid: c_int) -> c_int;
|
fn hid_init(vid: c_int, pid: c_int) -> c_int;
|
||||||
fn hid_identify() -> *const c_char;
|
fn hid_identify() -> *const c_char;
|
||||||
fn hid_close();
|
fn hid_close();
|
||||||
|
|
||||||
fn serial_close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -127,7 +125,7 @@ pub fn disconnect() {
|
|||||||
dfu_reboot();
|
dfu_reboot();
|
||||||
dfu_close();
|
dfu_close();
|
||||||
hid_close();
|
hid_close();
|
||||||
serial_close();
|
crate::serial::close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr};
|
||||||
use libc::{c_char};
|
use libc::{c_char};
|
||||||
|
use std::process::exit;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
fn find_path(vid: libc::c_int, pid: libc::c_int) -> *const c_char;
|
fn find_path(vid: libc::c_int, pid: libc::c_int) -> *const c_char;
|
||||||
fn serial_identify(s: *const c_char) -> *const c_char;
|
fn serial_identify(s: *const c_char) -> *const c_char;
|
||||||
|
fn serial_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to the specified device.
|
/// Connect to the specified device.
|
||||||
@ -23,17 +26,86 @@ pub fn serial_init(vid: u32, pid: u32, trace_flag: bool) -> Option<String> {
|
|||||||
Some(dev_path)
|
Some(dev_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn send_receive(port: &mut dyn serial::SerialPort, command: &[u8], reply_len: usize, trace: bool) -> Vec<u8> {
|
||||||
|
if trace {
|
||||||
|
eprintln!("----Send [{}] {:?}", command.len(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
match port.write(&command) {
|
||||||
|
Ok(n) => {
|
||||||
|
if trace {
|
||||||
|
eprintln!("Wrote {} bytes over serial", n);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Serial write error: {}", e);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buf: Vec<u8> = vec![0; reply_len];
|
||||||
|
match port.read(&mut buf) {
|
||||||
|
Ok(n) if n == reply_len => {
|
||||||
|
if trace {
|
||||||
|
eprintln!("----Received [{}] {:?}", reply_len, buf);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Ok(n) => {
|
||||||
|
eprintln!("Serial: read {} bytes, expected {}", n, reply_len);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Serial read error: {}", e);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
buf
|
||||||
|
}
|
||||||
|
|
||||||
/// Query and return the device identification string.
|
/// Query and return the device identification string.
|
||||||
/// On error, return None.
|
/// On error, return None.
|
||||||
pub fn identify(dev_path: &str) -> Option<String> {
|
pub fn identify(dev_path: &str) -> Option<String> {
|
||||||
let dev_path_c = CString::new(dev_path).unwrap();
|
use serial::prelude::*;
|
||||||
let ptr = dev_path_c.as_ptr() as *mut c_char;
|
|
||||||
unsafe {
|
let mut port = match serial::open(dev_path) {
|
||||||
let output = serial_identify(ptr);
|
Ok(port) => port,
|
||||||
if output.is_null() {
|
Err(err) => {
|
||||||
None
|
println!("{}", err);
|
||||||
} else {
|
exit(-1);
|
||||||
Some(CStr::from_ptr(output).to_str().unwrap().to_string())
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
port.reconfigure(&|settings: &mut dyn SerialPortSettings| {
|
||||||
|
settings.set_baud_rate(serial::BaudRate::Baud115200)?;
|
||||||
|
settings.set_char_size(serial::CharSize::Bits8);
|
||||||
|
Ok(())
|
||||||
|
}).unwrap();
|
||||||
|
port.set_timeout(Duration::new(1,0)).unwrap();
|
||||||
|
|
||||||
|
let program_cmd = b"PROGRAM";
|
||||||
|
let program_cmd_2 = b"\x02";
|
||||||
|
|
||||||
|
let program_ack = b"QX\x06";
|
||||||
|
let command_ack: u8 = b'\x06';
|
||||||
|
|
||||||
|
let output = send_receive(&mut port, program_cmd, 3, true);
|
||||||
|
if output != program_ack {
|
||||||
|
eprintln!("serial identify: wrong PRG acknowledge {:?}, expected {:?}", output, program_ack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expected output should be something like:
|
||||||
|
// 49 44 38 36 38 55 56 45 00 56 31 30 32 00 00 06
|
||||||
|
// I D 8 6 8 U V E V 1 0 2
|
||||||
|
let output = send_receive(&mut port, program_cmd_2, 16, true);
|
||||||
|
if (output[0] != 'I' as u8) || (output[15] != command_ack) {
|
||||||
|
eprintln!("serial identify: wrong PRG2 reply {:?} expected 'I'...'\\6'", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(String::from_utf8(output[1..7].to_vec()).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close the serial port.
|
||||||
|
pub fn close() {
|
||||||
|
unsafe {
|
||||||
|
serial_close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user