Skip to main content

android_usb_serial/
serialport_compat.rs

1//! `serialport` crate compatibility layer — full [`serialport::SerialPort`] on Android USB.
2//!
3//! Enable with Cargo feature `serialport-compat` (default). Wrap a [`crate::SerialPortHandle`]
4//! in [`SerialPortAdapter`](crate::serialport_compat::SerialPortAdapter) after
5//! [`crate::open_port`].
6
7use crate::config::{DataBits, FlowControl, LineConfig, Parity, PurgeKind, StopBits};
8use crate::error::UsbSerialError;
9use crate::port::SerialPortHandle;
10use serialport::{
11    ClearBuffer, DataBits as SpDataBits, FlowControl as SpFlowControl, Parity as SpParity,
12    SerialPort, StopBits as SpStopBits,
13};
14use std::collections::VecDeque;
15use std::io::{self, Read, Write};
16use std::sync::{Arc, Mutex};
17use std::thread;
18use std::time::{Duration, Instant};
19
20const DEFAULT_WRITE_CHUNK: usize = 512;
21const READ_POLL_MS: u64 = 1;
22
23/// USB bulk-OUT timeout per chunk: `max(clamp(port_timeout_ms, 1, 600_000), 2000)`.
24pub fn chunk_write_timeout_ms(port_timeout: Duration) -> u32 {
25    let ms = port_timeout.as_millis() as u64;
26    ms.clamp(1, 600_000).max(2000) as u32
27}
28
29fn usb_err(e: UsbSerialError) -> io::Error {
30    io::Error::other(e.to_string())
31}
32
33fn sp_err(e: UsbSerialError) -> serialport::Error {
34    serialport::Error::new(serialport::ErrorKind::Unknown, e.to_string())
35}
36
37struct SerialPortInner {
38    handle: Mutex<SerialPortHandle>,
39    name: String,
40    timeout: Mutex<Duration>,
41    line_config: Mutex<LineConfig>,
42    flow_control: Mutex<FlowControl>,
43    rx_ring: Mutex<VecDeque<u8>>,
44    write_chunk: usize,
45    reader_started: Mutex<bool>,
46}
47
48impl SerialPortInner {
49    fn new(
50        handle: SerialPortHandle,
51        name: String,
52        line_config: LineConfig,
53        flow_control: FlowControl,
54        write_chunk: usize,
55    ) -> Self {
56        Self {
57            handle: Mutex::new(handle),
58            name,
59            timeout: Mutex::new(Duration::from_millis(1000)),
60            line_config: Mutex::new(line_config),
61            flow_control: Mutex::new(flow_control),
62            rx_ring: Mutex::new(VecDeque::new()),
63            write_chunk: write_chunk.max(64),
64            reader_started: Mutex::new(false),
65        }
66    }
67
68    fn start_reader(&self) -> io::Result<()> {
69        let mut started = self.reader_started.lock().unwrap();
70        if *started {
71            return Ok(());
72        }
73        self.handle
74            .lock()
75            .unwrap()
76            .start_reader()
77            .map_err(usb_err)?;
78        *started = true;
79        Ok(())
80    }
81
82    fn ensure_reader_started(&self) -> io::Result<()> {
83        if *self.reader_started.lock().unwrap() {
84            return Ok(());
85        }
86        self.start_reader()
87    }
88
89    fn timeout(&self) -> Duration {
90        *self.timeout.lock().unwrap()
91    }
92
93    fn drain_ring(&self, buf: &mut [u8]) -> usize {
94        let mut ring = self.rx_ring.lock().unwrap();
95        let n = ring.len().min(buf.len());
96        for (dst, src) in buf[..n].iter_mut().zip(ring.drain(..n)) {
97            *dst = src;
98        }
99        n
100    }
101
102    fn push_ring(&self, data: &[u8]) {
103        if data.is_empty() {
104            return;
105        }
106        self.rx_ring.lock().unwrap().extend(data);
107    }
108
109    fn ring_len(&self) -> usize {
110        self.rx_ring.lock().unwrap().len()
111    }
112
113    fn clear_ring(&self) {
114        self.rx_ring.lock().unwrap().clear();
115    }
116
117    fn refill_from_reader(&self, scratch: &mut [u8]) -> io::Result<usize> {
118        let mut handle = self.handle.lock().unwrap();
119        handle.try_read(scratch).map_err(usb_err)
120    }
121
122    fn map_purge(kind: ClearBuffer) -> PurgeKind {
123        match kind {
124            ClearBuffer::Input => PurgeKind::Rx,
125            ClearBuffer::Output => PurgeKind::Tx,
126            ClearBuffer::All => PurgeKind::Both,
127        }
128    }
129}
130
131/// Shared [`serialport::SerialPort`] adapter over [`SerialPortHandle`] + background reader.
132#[derive(Clone)]
133pub struct SerialPortAdapter {
134    inner: Arc<SerialPortInner>,
135}
136
137impl SerialPortAdapter {
138    /// Wrap an open [`SerialPortHandle`]. Call [`Self::start_reader`] after line/DTR setup.
139    pub fn new(
140        handle: SerialPortHandle,
141        name: impl Into<String>,
142        line_config: LineConfig,
143        flow_control: FlowControl,
144    ) -> io::Result<Self> {
145        Ok(Self {
146            inner: Arc::new(SerialPortInner::new(
147                handle,
148                name.into(),
149                line_config,
150                flow_control,
151                DEFAULT_WRITE_CHUNK,
152            )),
153        })
154    }
155
156    /// Start background bulk-IN reader after line/DTR setup (avoids racing driver init on OTG).
157    pub fn start_reader(&self) -> io::Result<()> {
158        self.inner.start_reader()
159    }
160
161    /// Stop background reader and close the USB driver (idempotent).
162    pub fn shutdown(&self) {
163        let mut handle = self.inner.handle.lock().unwrap();
164        handle.stop_reader();
165        handle.close();
166        self.inner.clear_ring();
167    }
168
169    pub fn with_write_chunk(mut self, chunk: usize) -> Self {
170        if let Some(inner) = Arc::get_mut(&mut self.inner) {
171            inner.write_chunk = chunk.max(64);
172        }
173        self
174    }
175}
176
177impl Read for SerialPortAdapter {
178    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
179        if buf.is_empty() {
180            return Ok(0);
181        }
182        self.inner.ensure_reader_started()?;
183        let deadline = Instant::now() + self.inner.timeout();
184        let mut scratch = [0u8; 4096];
185        loop {
186            let n = self.inner.drain_ring(buf);
187            if n > 0 {
188                return Ok(n);
189            }
190            match self.inner.refill_from_reader(&mut scratch) {
191                Ok(0) => {
192                    if Instant::now() >= deadline {
193                        return Ok(0);
194                    }
195                    thread::sleep(Duration::from_millis(READ_POLL_MS));
196                }
197                Ok(n) => self.inner.push_ring(&scratch[..n]),
198                Err(e) => {
199                    let kind = e.kind();
200                    if kind == io::ErrorKind::TimedOut || kind == io::ErrorKind::WouldBlock {
201                        if Instant::now() >= deadline {
202                            return Ok(0);
203                        }
204                        thread::sleep(Duration::from_millis(READ_POLL_MS));
205                    } else {
206                        return Err(e);
207                    }
208                }
209            }
210        }
211    }
212}
213
214impl Write for SerialPortAdapter {
215    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
216        if buf.is_empty() {
217            return Ok(0);
218        }
219        let chunk = self.inner.write_chunk;
220        let mut handle = self.inner.handle.lock().unwrap();
221        let mut offset = 0usize;
222        while offset < buf.len() {
223            let end = (offset + chunk).min(buf.len());
224            let n = handle.write(&buf[offset..end]).map_err(usb_err)?;
225            if n == 0 {
226                return Err(io::Error::new(
227                    io::ErrorKind::WriteZero,
228                    "USB write returned 0",
229                ));
230            }
231            offset += n;
232        }
233        Ok(buf.len())
234    }
235
236    fn flush(&mut self) -> io::Result<()> {
237        Ok(())
238    }
239}
240
241impl SerialPort for SerialPortAdapter {
242    fn name(&self) -> Option<String> {
243        Some(self.inner.name.clone())
244    }
245
246    fn baud_rate(&self) -> serialport::Result<u32> {
247        Ok(self.inner.line_config.lock().unwrap().baud_rate)
248    }
249
250    fn data_bits(&self) -> serialport::Result<SpDataBits> {
251        Ok(match self.inner.line_config.lock().unwrap().data_bits {
252            DataBits::Five => SpDataBits::Five,
253            DataBits::Six => SpDataBits::Six,
254            DataBits::Seven => SpDataBits::Seven,
255            DataBits::Eight => SpDataBits::Eight,
256        })
257    }
258
259    fn flow_control(&self) -> serialport::Result<SpFlowControl> {
260        Ok(match *self.inner.flow_control.lock().unwrap() {
261            FlowControl::None => SpFlowControl::None,
262            FlowControl::RtsCts | FlowControl::DtrDsr => SpFlowControl::Hardware,
263            FlowControl::XonXoff | FlowControl::XonXoffInline => SpFlowControl::Software,
264        })
265    }
266
267    fn parity(&self) -> serialport::Result<SpParity> {
268        Ok(match self.inner.line_config.lock().unwrap().parity {
269            Parity::None => SpParity::None,
270            Parity::Odd => SpParity::Odd,
271            Parity::Even => SpParity::Even,
272            Parity::Mark | Parity::Space => SpParity::None,
273        })
274    }
275
276    fn stop_bits(&self) -> serialport::Result<SpStopBits> {
277        Ok(match self.inner.line_config.lock().unwrap().stop_bits {
278            StopBits::One | StopBits::OnePointFive => SpStopBits::One,
279            StopBits::Two => SpStopBits::Two,
280        })
281    }
282
283    fn timeout(&self) -> Duration {
284        self.inner.timeout()
285    }
286
287    fn set_baud_rate(&mut self, baud_rate: u32) -> serialport::Result<()> {
288        let mut cfg = self.inner.line_config.lock().unwrap();
289        cfg.baud_rate = baud_rate;
290        self.inner
291            .handle
292            .lock()
293            .unwrap()
294            .set_line_config(*cfg)
295            .map_err(sp_err)
296    }
297
298    fn set_data_bits(&mut self, data_bits: SpDataBits) -> serialport::Result<()> {
299        let mut cfg = self.inner.line_config.lock().unwrap();
300        cfg.data_bits = match data_bits {
301            SpDataBits::Five => DataBits::Five,
302            SpDataBits::Six => DataBits::Six,
303            SpDataBits::Seven => DataBits::Seven,
304            SpDataBits::Eight => DataBits::Eight,
305        };
306        self.inner
307            .handle
308            .lock()
309            .unwrap()
310            .set_line_config(*cfg)
311            .map_err(sp_err)
312    }
313
314    fn set_flow_control(&mut self, flow_control: SpFlowControl) -> serialport::Result<()> {
315        let flow = match flow_control {
316            SpFlowControl::None => FlowControl::None,
317            SpFlowControl::Hardware => FlowControl::RtsCts,
318            SpFlowControl::Software => FlowControl::XonXoff,
319        };
320        *self.inner.flow_control.lock().unwrap() = flow;
321        self.inner
322            .handle
323            .lock()
324            .unwrap()
325            .set_flow_control(flow)
326            .map_err(sp_err)
327    }
328
329    fn set_parity(&mut self, parity: SpParity) -> serialport::Result<()> {
330        let mut cfg = self.inner.line_config.lock().unwrap();
331        cfg.parity = match parity {
332            SpParity::None => Parity::None,
333            SpParity::Odd => Parity::Odd,
334            SpParity::Even => Parity::Even,
335        };
336        self.inner
337            .handle
338            .lock()
339            .unwrap()
340            .set_line_config(*cfg)
341            .map_err(sp_err)
342    }
343
344    fn set_stop_bits(&mut self, stop_bits: SpStopBits) -> serialport::Result<()> {
345        let mut cfg = self.inner.line_config.lock().unwrap();
346        cfg.stop_bits = match stop_bits {
347            SpStopBits::One => StopBits::One,
348            SpStopBits::Two => StopBits::Two,
349        };
350        self.inner
351            .handle
352            .lock()
353            .unwrap()
354            .set_line_config(*cfg)
355            .map_err(sp_err)
356    }
357
358    fn set_timeout(&mut self, timeout: Duration) -> serialport::Result<()> {
359        *self.inner.timeout.lock().unwrap() = timeout;
360        Ok(())
361    }
362
363    fn write_request_to_send(&mut self, level: bool) -> serialport::Result<()> {
364        self.inner
365            .handle
366            .lock()
367            .unwrap()
368            .set_rts(level)
369            .map_err(sp_err)
370    }
371
372    fn write_data_terminal_ready(&mut self, level: bool) -> serialport::Result<()> {
373        self.inner
374            .handle
375            .lock()
376            .unwrap()
377            .set_dtr(level)
378            .map_err(sp_err)
379    }
380
381    fn read_clear_to_send(&mut self) -> serialport::Result<bool> {
382        Ok(self
383            .inner
384            .handle
385            .lock()
386            .unwrap()
387            .modem_status()
388            .map_err(sp_err)?
389            .cts)
390    }
391
392    fn read_data_set_ready(&mut self) -> serialport::Result<bool> {
393        Ok(self
394            .inner
395            .handle
396            .lock()
397            .unwrap()
398            .modem_status()
399            .map_err(sp_err)?
400            .dsr)
401    }
402
403    fn read_ring_indicator(&mut self) -> serialport::Result<bool> {
404        Ok(self
405            .inner
406            .handle
407            .lock()
408            .unwrap()
409            .modem_status()
410            .map_err(sp_err)?
411            .ri)
412    }
413
414    fn read_carrier_detect(&mut self) -> serialport::Result<bool> {
415        Ok(self
416            .inner
417            .handle
418            .lock()
419            .unwrap()
420            .modem_status()
421            .map_err(sp_err)?
422            .cd)
423    }
424
425    fn bytes_to_read(&self) -> serialport::Result<u32> {
426        Ok(self.inner.ring_len() as u32)
427    }
428
429    fn bytes_to_write(&self) -> serialport::Result<u32> {
430        Ok(0)
431    }
432
433    fn clear(&self, buffer_to_clear: ClearBuffer) -> serialport::Result<()> {
434        if matches!(buffer_to_clear, ClearBuffer::Input | ClearBuffer::All) {
435            self.inner.clear_ring();
436        }
437        self.inner
438            .handle
439            .lock()
440            .unwrap()
441            .clear(SerialPortInner::map_purge(buffer_to_clear))
442            .map_err(sp_err)
443    }
444
445    fn try_clone(&self) -> serialport::Result<Box<dyn SerialPort>> {
446        Ok(Box::new(SerialPortAdapter {
447            inner: self.inner.clone(),
448        }))
449    }
450
451    fn set_break(&self) -> serialport::Result<()> {
452        self.inner
453            .handle
454            .lock()
455            .unwrap()
456            .set_break(true)
457            .map_err(sp_err)
458    }
459
460    fn clear_break(&self) -> serialport::Result<()> {
461        self.inner
462            .handle
463            .lock()
464            .unwrap()
465            .set_break(false)
466            .map_err(sp_err)
467    }
468}
469
470pub fn line_config_from_serialport(
471    baud_rate: u32,
472    data_bits: SpDataBits,
473    parity: SpParity,
474    stop_bits: SpStopBits,
475) -> LineConfig {
476    LineConfig {
477        baud_rate,
478        data_bits: match data_bits {
479            SpDataBits::Five => DataBits::Five,
480            SpDataBits::Six => DataBits::Six,
481            SpDataBits::Seven => DataBits::Seven,
482            SpDataBits::Eight => DataBits::Eight,
483        },
484        parity: match parity {
485            SpParity::None => Parity::None,
486            SpParity::Odd => Parity::Odd,
487            SpParity::Even => Parity::Even,
488        },
489        stop_bits: match stop_bits {
490            SpStopBits::One => StopBits::One,
491            SpStopBits::Two => StopBits::Two,
492        },
493    }
494}
495
496pub fn flow_from_serialport(flow: SpFlowControl) -> FlowControl {
497    match flow {
498        SpFlowControl::None => FlowControl::None,
499        SpFlowControl::Hardware => FlowControl::RtsCts,
500        SpFlowControl::Software => FlowControl::XonXoff,
501    }
502}