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 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#[derive(Clone)]
133pub struct SerialPortAdapter {
134 inner: Arc<SerialPortInner>,
135}
136
137impl SerialPortAdapter {
138 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 pub fn start_reader(&self) -> io::Result<()> {
158 self.inner.start_reader()
159 }
160
161 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}