1use std::{
2 io::{self, Error, ErrorKind, Read, Write},
3 time::Duration,
4};
5
6use crate::SerialConfig;
7use crate::{
8 usb::{self, DeviceInfo, InterfaceInfo, SyncReader, SyncWriter},
9 UsbSerial,
10};
11use nusb::transfer::{Control, ControlType, Direction, Queue, Recipient, RequestBuffer};
12
13use serialport::{DataBits, Parity, SerialPort, StopBits};
14
15const USB_INTR_CLASS_COMM: u8 = 0x02;
16const USB_INTR_SUBCLASS_ACM: u8 = 0x02;
17const USB_INTR_CLASS_CDC_DATA: u8 = 0x0A;
18
19const SET_LINE_CODING: u8 = 0x20;
20const SET_CONTROL_LINE_STATE: u8 = 0x22;
21const SEND_BREAK: u8 = 0x23;
22
23pub struct CdcSerial {
30 usb_path_name: String, ctrl_index: u16, intr_comm: nusb::Interface, reader: SyncReader, writer: SyncWriter, timeout: Duration, ser_conf: Option<SerialConfig>, dtr_rts: (bool, bool), }
40
41impl CdcSerial {
42 pub fn probe() -> io::Result<Vec<DeviceInfo>> {
45 let devs = usb::list_devices()?;
46 Ok(devs
47 .into_iter()
48 .filter(|dev| Self::find_interfaces(dev).is_some())
49 .collect())
50 }
51
52 pub fn build(dev_info: &DeviceInfo, timeout: Duration) -> io::Result<Self> {
56 let (intr_comm, intr_data) = Self::find_interfaces(dev_info)
57 .ok_or(Error::new(ErrorKind::InvalidInput, "Not a CDC-ACM device"))?;
58 let ctrl_index = intr_comm.interface_number() as u16;
59
60 let device = dev_info.open_device()?;
61 let intr_comm = device.detach_and_claim_interface(intr_comm.interface_number())?;
62 let intr_data = device.detach_and_claim_interface(intr_data.interface_number())?;
63
64 let (mut addr_r, mut addr_w) = (None, None);
66 for alt in intr_data.descriptors() {
67 let endps: Vec<_> = alt.endpoints().collect();
68 let endp_r = endps.iter().find(|endp| endp.direction() == Direction::In);
69 let endp_w = endps.iter().find(|endp| endp.direction() == Direction::Out);
70 if let (Some(endp_r), Some(endp_w)) = (endp_r, endp_w) {
71 addr_r = Some(endp_r.address());
72 addr_w = Some(endp_w.address());
73 break;
74 }
75 }
76 let (reader, writer) = if let (Some(r), Some(w)) = (addr_r, addr_w) {
77 (
78 SyncReader::new(intr_data.bulk_in_queue(r)),
79 SyncWriter::new(intr_data.bulk_out_queue(w)),
80 )
81 } else {
82 return Err(Error::new(ErrorKind::NotFound, "Data endpoints not found"));
83 };
84
85 Ok(Self {
86 usb_path_name: dev_info.path_name().clone(),
87 ctrl_index,
88 intr_comm,
89 reader,
90 writer,
91 timeout,
92 ser_conf: None,
93 dtr_rts: (false, false),
94 })
95 }
96
97 fn find_interfaces(dev_info: &DeviceInfo) -> Option<(InterfaceInfo, InterfaceInfo)> {
99 let (comm, data) = (
100 dev_info.interfaces().find(|intr| {
101 intr.class() == USB_INTR_CLASS_COMM && intr.sub_class() == USB_INTR_SUBCLASS_ACM
102 }),
103 dev_info
104 .interfaces()
105 .find(|intr| intr.class() == USB_INTR_CLASS_CDC_DATA),
106 );
107 if let (Some(comm), Some(data)) = (comm, data) {
108 Some((*comm, *data))
109 } else {
110 None
111 }
112 }
113
114 pub fn set_config(&mut self, conf: SerialConfig) -> io::Result<()> {
116 let conf_bytes: [u8; 7] = conf.line_coding_bytes();
117 self.control_set(SET_LINE_CODING, 0, &conf_bytes)?;
118 self.ser_conf.replace(conf);
119 Ok(())
120 }
121
122 fn set_dtr_rts(&mut self, dtr: bool, rts: bool) -> io::Result<()> {
124 let val_dtr = if dtr { 0x1 } else { 0x0 };
125 let val_rts = if rts { 0x2 } else { 0x0 };
126 let val = (val_dtr | val_rts) as u16;
127 self.control_set(SET_CONTROL_LINE_STATE, val, &[])?;
128 self.dtr_rts = (dtr, rts);
129 Ok(())
130 }
131
132 fn set_break_state(&self, val: bool) -> io::Result<()> {
134 let val = if val { 0xffff } else { 0 } as u16;
135 self.control_set(SEND_BREAK, val, &[])
136 }
137
138 fn control_set(&self, request: u8, value: u16, buf: &[u8]) -> io::Result<()> {
139 use nusb::transfer::TransferError;
140 let sz_write = self
141 .intr_comm
142 .control_out_blocking(
143 Control {
144 control_type: ControlType::Class,
145 recipient: Recipient::Interface,
146 request,
147 value,
148 index: self.ctrl_index,
149 },
150 buf,
151 self.timeout * 2,
152 )
153 .map_err(|e| match e {
154 TransferError::Disconnected => Error::from(ErrorKind::NotConnected),
155 _ => Error::other(e),
156 })?;
157 if sz_write == buf.len() {
158 Ok(())
159 } else {
160 Err(Error::new(
161 ErrorKind::Interrupted,
162 "control_set(), wrong written size",
163 ))
164 }
165 }
166}
167
168impl Read for CdcSerial {
169 #[inline]
170 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
171 self.reader.read(buf, self.timeout)
172 }
173}
174
175impl Write for CdcSerial {
176 #[inline]
177 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
178 self.writer.write(buf, self.timeout)
179 }
180 fn flush(&mut self) -> io::Result<()> {
182 Ok(())
183 }
184}
185
186impl SerialConfig {
187 fn line_coding_bytes(&self) -> [u8; 7] {
188 let mut bytes = [0u8; 7];
189 bytes[..4].copy_from_slice(&self.baud_rate.to_le_bytes());
190 bytes[4] = match self.stop_bits {
191 StopBits::One => 0u8,
192 StopBits::Two => 2u8,
193 };
194 bytes[5] = match self.parity {
195 Parity::None => 0u8,
196 Parity::Odd => 1u8,
197 Parity::Even => 2u8,
198 };
199 bytes[6] = match self.data_bits {
200 DataBits::Five => 5,
201 DataBits::Six => 6,
202 DataBits::Seven => 7,
203 DataBits::Eight => 8,
204 };
205 bytes
206 }
207}
208
209#[inline(always)]
210fn err_map_to_serialport(err: Error) -> serialport::Error {
211 let desc = err.to_string();
212 let kind = match err.kind() {
213 ErrorKind::NotConnected => serialport::ErrorKind::NoDevice,
214 ErrorKind::InvalidInput => serialport::ErrorKind::InvalidInput,
215 _ => serialport::ErrorKind::Io(err.kind()),
216 };
217 serialport::Error::new(kind, desc)
218}
219
220fn err_unsupported_op() -> serialport::Error {
221 err_map_to_serialport(Error::new(
222 ErrorKind::Unsupported,
223 "unsupported function in trait `Serialport`",
224 ))
225}
226
227impl CdcSerial {
228 #[inline]
229 fn get_conf_for_serialport(&self) -> Result<&SerialConfig, serialport::Error> {
230 self.ser_conf.as_ref().ok_or(serialport::Error::new(
231 serialport::ErrorKind::Io(std::io::ErrorKind::NotFound),
232 "serial configuration haven't been set",
233 ))
234 }
235}
236
237impl SerialPort for CdcSerial {
238 fn name(&self) -> Option<String> {
239 Some(self.usb_path_name.clone())
240 }
241
242 fn baud_rate(&self) -> serialport::Result<u32> {
243 Ok(self.get_conf_for_serialport()?.baud_rate)
244 }
245 fn data_bits(&self) -> serialport::Result<serialport::DataBits> {
246 Ok(self.get_conf_for_serialport()?.data_bits)
247 }
248 fn parity(&self) -> serialport::Result<serialport::Parity> {
249 Ok(self.get_conf_for_serialport()?.parity)
250 }
251 fn stop_bits(&self) -> serialport::Result<serialport::StopBits> {
252 Ok(self.get_conf_for_serialport()?.stop_bits)
253 }
254
255 fn flow_control(&self) -> serialport::Result<serialport::FlowControl> {
256 Ok(serialport::FlowControl::None)
257 }
258
259 fn timeout(&self) -> Duration {
260 self.timeout
261 }
262
263 fn set_baud_rate(&mut self, baud_rate: u32) -> serialport::Result<()> {
264 let mut conf = self.ser_conf.unwrap_or_default();
265 conf.baud_rate = baud_rate;
266 self.set_config(conf).map_err(err_map_to_serialport)
267 }
268
269 fn set_data_bits(&mut self, data_bits: serialport::DataBits) -> serialport::Result<()> {
270 let mut conf = self.ser_conf.unwrap_or_default();
271 conf.data_bits = data_bits;
272 self.set_config(conf).map_err(err_map_to_serialport)
273 }
274
275 fn set_parity(&mut self, parity: serialport::Parity) -> serialport::Result<()> {
276 let mut conf = self.ser_conf.unwrap_or_default();
277 conf.parity = parity;
278 self.set_config(conf).map_err(err_map_to_serialport)
279 }
280
281 fn set_stop_bits(&mut self, stop_bits: serialport::StopBits) -> serialport::Result<()> {
282 let mut conf = self.ser_conf.unwrap_or_default();
283 conf.stop_bits = stop_bits;
284 self.set_config(conf).map_err(err_map_to_serialport)
285 }
286
287 fn set_flow_control(
288 &mut self,
289 _flow_control: serialport::FlowControl,
290 ) -> serialport::Result<()> {
291 Err(err_unsupported_op())
292 }
293
294 fn set_timeout(&mut self, timeout: Duration) -> serialport::Result<()> {
296 self.timeout = timeout;
297 Ok(())
298 }
299
300 #[inline(always)]
301 fn write_request_to_send(&mut self, value: bool) -> serialport::Result<()> {
302 let (dtr, _) = self.dtr_rts;
303 let rts = value;
304 self.set_dtr_rts(dtr, rts).map_err(err_map_to_serialport)
305 }
306
307 #[inline(always)]
308 fn write_data_terminal_ready(&mut self, value: bool) -> serialport::Result<()> {
309 let (_, rts) = self.dtr_rts;
310 let dtr = value;
311 self.set_dtr_rts(dtr, rts).map_err(err_map_to_serialport)
312 }
313
314 fn read_clear_to_send(&mut self) -> serialport::Result<bool> {
316 Err(err_unsupported_op())
317 }
318 fn read_data_set_ready(&mut self) -> serialport::Result<bool> {
320 Err(err_unsupported_op())
321 }
322 fn read_ring_indicator(&mut self) -> serialport::Result<bool> {
324 Err(err_unsupported_op())
325 }
326 fn read_carrier_detect(&mut self) -> serialport::Result<bool> {
328 Err(err_unsupported_op())
329 }
330
331 #[inline(always)]
333 fn bytes_to_read(&self) -> serialport::Result<u32> {
334 Ok(0)
335 }
336 #[inline(always)]
338 fn bytes_to_write(&self) -> serialport::Result<u32> {
339 Ok(0)
340 }
341 fn clear(&self, _buffer_to_clear: serialport::ClearBuffer) -> serialport::Result<()> {
343 Ok(())
344 }
345
346 #[inline(always)]
347 fn set_break(&self) -> serialport::Result<()> {
348 self.set_break_state(true).map_err(err_map_to_serialport)
349 }
350 #[inline(always)]
351 fn clear_break(&self) -> serialport::Result<()> {
352 self.set_break_state(false).map_err(err_map_to_serialport)
353 }
354
355 fn try_clone(&self) -> serialport::Result<Box<dyn serialport::SerialPort>> {
357 Err(err_unsupported_op())
358 }
359}
360
361impl UsbSerial for CdcSerial {
362 fn configure(&mut self, conf: &SerialConfig) -> std::io::Result<()> {
363 self.set_config(*conf)
364 }
365
366 fn into_queues(self) -> (Queue<RequestBuffer>, Queue<Vec<u8>>) {
367 (self.reader.into(), self.writer.into())
368 }
369
370 fn sealer(_: crate::private::Internal) {}
371}