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