lin_bus_driver_serial/
lib.rs

1pub extern crate lin_bus;
2pub extern crate serial;
3
4use lin_bus::{driver, PID};
5use serial::{SerialPort, SystemPort};
6use std::io::{Read, Write};
7use std::thread::sleep;
8use std::time::Duration;
9
10pub struct SerialLin(pub SystemPort);
11
12#[derive(Debug)]
13pub enum SerialError {
14    LinError(driver::Error),
15    SerialError(serial::Error),
16}
17
18impl From<serial::Error> for SerialError {
19    fn from(error: serial::Error) -> SerialError {
20        SerialError::SerialError(error)
21    }
22}
23
24impl From<SerialError> for driver::Error {
25    fn from(error: SerialError) -> driver::Error {
26        match error {
27            SerialError::LinError(lin_error) => lin_error,
28            SerialError::SerialError(ser_error) => match ser_error.kind() {
29                serial::ErrorKind::Io(std::io::ErrorKind::TimedOut) => driver::Error::Timeout,
30                _ => driver::Error::PhysicalBus,
31            },
32        }
33    }
34}
35
36impl From<driver::Error> for SerialError {
37    fn from(error: driver::Error) -> SerialError {
38        SerialError::LinError(error)
39    }
40}
41
42impl From<std::io::Error> for SerialError {
43    fn from(error: std::io::Error) -> SerialError {
44        SerialError::SerialError(serial::Error::from(error))
45    }
46}
47
48impl driver::Master for SerialLin {
49    type Error = SerialError;
50
51    fn send_wakeup(&mut self) -> Result<(), SerialError> {
52        self.0.set_timeout(Duration::from_millis(1000))?;
53
54        self.0.reconfigure(&|settings| {
55            settings.set_baud_rate(serial::Baud9600)?;
56            settings.set_char_size(serial::Bits7);
57            settings.set_parity(serial::ParityNone);
58            settings.set_stop_bits(serial::Stop1);
59            settings.set_flow_control(serial::FlowNone);
60            Ok(())
61        })?;
62
63        self.0.write(&[0])?;
64        let mut buf = [0; 1];
65        self.0.read_exact(&mut buf)?;
66
67        if buf[0] != 0 {
68            Err(SerialError::LinError(driver::Error::PhysicalBus))
69        } else {
70            sleep(Duration::from_millis(100));
71            Ok(())
72        }
73    }
74
75    fn send_header(&mut self, pid: PID) -> Result<(), SerialError> {
76        self.0.set_timeout(Duration::from_millis(1000))?;
77
78        self.0.reconfigure(&|settings| {
79            settings.set_baud_rate(serial::Baud9600)?;
80            settings.set_char_size(serial::Bits7);
81            settings.set_parity(serial::ParityNone);
82            settings.set_stop_bits(serial::Stop1);
83            settings.set_flow_control(serial::FlowNone);
84            Ok(())
85        })?;
86
87        self.0.write(&[0])?;
88        // wait a short time before switching baudrate again, otherwise the zero byte won't be sent
89        // with the lower baudrate
90        sleep(Duration::from_millis(1));
91
92        self.0.reconfigure(&|settings| {
93            settings.set_baud_rate(serial::Baud19200)?;
94            settings.set_char_size(serial::Bits8);
95            settings.set_parity(serial::ParityNone);
96            settings.set_stop_bits(serial::Stop1);
97            settings.set_flow_control(serial::FlowNone);
98            Ok(())
99        })?;
100
101        self.0.write(&[0x55, pid.get()])?;
102
103        let mut buf = [0; 2];
104        self.0.read_exact(&mut buf)?;
105
106        if buf != [0x55, pid.get()] {
107            Err(SerialError::LinError(driver::Error::PhysicalBus))
108        } else {
109            Ok(())
110        }
111    }
112
113    fn read(&mut self, buf: &mut [u8]) -> Result<(), SerialError> {
114        self.0.read_exact(buf)?;
115        Ok(())
116    }
117    fn write(&mut self, data: &[u8]) -> Result<(), SerialError> {
118        assert!(
119            data.len() <= 9,
120            "Data must be at most 8 bytes + 1 checksum byte"
121        );
122        self.0.write(data)?;
123        let mut buf = [0; 9];
124        self.0.read_exact(&mut buf[0..data.len()])?;
125        if &buf[0..data.len()] != data {
126            Err(SerialError::LinError(driver::Error::PhysicalBus))
127        } else {
128            Ok(())
129        }
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    #[test]
136    fn it_works() {
137        assert_eq!(2 + 2, 4);
138    }
139}