Skip to main content

zmk_studio_api/transport/
serial.rs

1use std::io::{Read, Write};
2use std::time::Duration;
3
4const DEFAULT_BAUD_RATE: u32 = 12_500;
5const DEFAULT_TIMEOUT: Duration = Duration::from_millis(500);
6
7#[derive(Debug)]
8pub enum SerialTransportError {
9    Open(serialport::Error),
10    NoMatchingPort,
11}
12
13impl std::fmt::Display for SerialTransportError {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        match self {
16            Self::Open(err) => write!(f, "Failed to open serial port: {err}"),
17            Self::NoMatchingPort => write!(f, "No matching serial port found"),
18        }
19    }
20}
21
22impl std::error::Error for SerialTransportError {
23    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
24        match self {
25            Self::Open(err) => Some(err),
26            Self::NoMatchingPort => None,
27        }
28    }
29}
30
31impl From<serialport::Error> for SerialTransportError {
32    fn from(value: serialport::Error) -> Self {
33        Self::Open(value)
34    }
35}
36
37pub struct SerialTransport {
38    inner: Box<dyn serialport::SerialPort>,
39}
40
41impl SerialTransport {
42    pub fn open(path: &str) -> Result<Self, SerialTransportError> {
43        Self::open_with(path, DEFAULT_BAUD_RATE, DEFAULT_TIMEOUT)
44    }
45
46    fn open_with(
47        path: &str,
48        baud_rate: u32,
49        timeout: Duration,
50    ) -> Result<Self, SerialTransportError> {
51        let port = serialport::new(path, baud_rate).timeout(timeout).open()?;
52        Ok(Self { inner: port })
53    }
54}
55
56impl Read for SerialTransport {
57    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
58        self.inner.read(buf)
59    }
60}
61
62impl Write for SerialTransport {
63    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
64        self.inner.write(buf)
65    }
66
67    fn flush(&mut self) -> std::io::Result<()> {
68        self.inner.flush()
69    }
70}