dmx_serial/lib.rs
1use std::default::Default;
2use std::error::Error as StdError;
3use std::ffi::OsStr;
4use std::fmt;
5use std::io;
6use std::time::Duration;
7
8
9pub use BaudRate::*;
10pub use CharSize::*;
11pub use Parity::*;
12pub use StopBits::*;
13pub use FlowControl::*;
14
15/// A module that exports traits that are useful to have in scope.
16///
17/// It is intended to be glob imported:
18///
19/// ```no_run
20/// use serial::prelude::*;
21/// ```
22pub mod prelude {
23 pub use ::{SerialPort,SerialPortSettings};
24}
25
26#[cfg(unix)]
27pub mod posix;
28
29#[cfg(windows)]
30pub mod windows;
31
32
33/// A type for results generated by interacting with serial ports.
34///
35/// The `Err` type is hard-wired to [`serial::Error`](struct.Error.html).
36pub type Result<T> = std::result::Result<T,::Error>;
37
38/// Categories of errors that can occur when interacting with serial ports.
39///
40/// This list is intended to grow over time and it is not recommended to exhaustively match against it.
41#[derive(Debug,Clone,Copy,PartialEq,Eq)]
42pub enum ErrorKind {
43 /// The device is not available.
44 ///
45 /// This could indicate that the device is in use by another process or was disconnected while
46 /// performing I/O.
47 NoDevice,
48
49 /// A parameter was incorrect.
50 InvalidInput,
51
52 /// An I/O error occured.
53 ///
54 /// The type of I/O error is determined by the inner `io::ErrorKind`.
55 Io(io::ErrorKind)
56}
57
58/// An error type for serial port operations.
59#[derive(Debug)]
60pub struct Error {
61 kind: ErrorKind,
62 description: String
63}
64
65impl Error {
66 pub fn new<T: Into<String>>(kind: ErrorKind, description: T) -> Self {
67 Error {
68 kind: kind,
69 description: description.into()
70 }
71 }
72
73 /// Returns the corresponding `ErrorKind` for this error.
74 pub fn kind(&self) -> ErrorKind {
75 self.kind
76 }
77}
78
79impl fmt::Display for Error {
80 fn fmt(&self, fmt: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
81 fmt.write_str(&self.description)
82 }
83}
84
85impl StdError for Error {
86 fn description(&self) -> &str {
87 &self.description
88 }
89}
90
91impl From<io::Error> for Error {
92 fn from(io_error: io::Error) -> Error {
93 Error::new(ErrorKind::Io(io_error.kind()), format!("{}", io_error))
94 }
95}
96
97impl From<Error> for io::Error {
98 fn from(error: Error) -> io::Error {
99 let kind = match error.kind {
100 ErrorKind::NoDevice => io::ErrorKind::NotFound,
101 ErrorKind::InvalidInput => io::ErrorKind::InvalidInput,
102 ErrorKind::Io(kind) => kind
103 };
104
105 io::Error::new(kind, error.description)
106 }
107}
108
109/// A convenience type alias for the system's native serial port type.
110#[cfg(unix)]
111pub type SystemPort = posix::TTYPort;
112
113/// A convenience type alias for the system's native serial port type.
114#[cfg(windows)]
115pub type SystemPort = windows::COMPort;
116
117/// A convenience function for opening a native serial port.
118///
119/// The argument must be one that's understood by the target operating system to identify a serial
120/// port. On Unix systems, it should be a path to a TTY device file. On Windows, it should be the
121/// name of a COM port.
122///
123/// ## Errors
124///
125/// This function returns an error if the device could not be opened and initialized:
126///
127/// * `NoDevice` if the device could not be opened. This could indicate that the device is
128/// already in use.
129/// * `InvalidInput` if `port` is not a valid device name.
130/// * `Io` for any other error while opening or initializing the device.
131///
132/// ## Examples
133///
134/// Provide a system-specific string that identifies a serial port:
135///
136/// ```no_run
137/// let port = serial::open("/dev/ttyUSB0").unwrap();
138/// ```
139///
140/// Hard-coding the device name dimishes the cross-platform utility of `serial::open()`. To
141/// preserve cross-platform functionality, device names should come from external sources:
142///
143/// ```no_run
144/// use std::env;
145///
146/// for arg in env::args_os().skip(1) {
147/// let port = serial::open(&arg).unwrap();
148/// }
149/// ```
150#[cfg(unix)]
151pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> ::Result<SystemPort> {
152 use std::path::Path;
153 posix::TTYPort::open(Path::new(port))
154}
155
156/// A convenience function for opening a native serial port.
157///
158/// The argument must be one that's understood by the target operating system to identify a serial
159/// port. On Unix systems, it should be a path to a TTY device file. On Windows, it should be the
160/// name of a COM port.
161///
162/// ## Errors
163///
164/// This function returns an error if the device could not be opened and initialized:
165///
166/// * `NoDevice` if the device could not be opened. This could indicate that the device is
167/// already in use.
168/// * `InvalidInput` if `port` is not a valid device name.
169/// * `Io` for any other error while opening or initializing the device.
170///
171/// ## Examples
172///
173/// Provide a system-specific string that identifies a serial port:
174///
175/// ```no_run
176/// let port = serial::open("COM1").unwrap();
177/// ```
178///
179/// Hard-coding the device name dimishes the cross-platform utility of `serial::open()`. To
180/// preserve cross-platform functionality, device names should come from external sources:
181///
182/// ```no_run
183/// use std::env;
184///
185/// for arg in env::args_os().skip(1) {
186/// let port = serial::open(&arg).unwrap();
187/// }
188/// ```
189#[cfg(windows)]
190pub fn open<T: AsRef<OsStr> + ?Sized>(port: &T) -> ::Result<SystemPort> {
191 windows::COMPort::open(port)
192}
193
194
195/// Serial port baud rates.
196///
197/// ## Portability
198///
199/// The `BaudRate` variants with numeric suffixes, e.g., `Baud9600`, indicate standard baud rates
200/// that are widely-supported on many systems. While non-standard baud rates can be set with
201/// `BaudOther`, their behavior is system-dependent. Some systems may not support arbitrary baud
202/// rates. Using the standard baud rates is more likely to result in portable applications.
203#[derive(Debug,Copy,Clone,PartialEq,Eq)]
204pub enum BaudRate {
205 /** 110 baud. */ Baud110,
206 /** 300 baud. */ Baud300,
207 /** 600 baud. */ Baud600,
208 /** 1200 baud. */ Baud1200,
209 /** 2400 baud. */ Baud2400,
210 /** 4800 baud. */ Baud4800,
211 /** 9600 baud. */ Baud9600,
212 /** 19,200 baud. */ Baud19200,
213 /** 38,400 baud. */ Baud38400,
214 /** 57,600 baud. */ Baud57600,
215 /** 115,200 baud. */ Baud115200,
216
217 /// Non-standard baud rates.
218 ///
219 /// `BaudOther` can be used to set non-standard baud rates by setting its member to be the
220 /// desired baud rate.
221 ///
222 /// ```no_run
223 /// serial::BaudOther(4_000_000); // 4,000,000 baud
224 /// ```
225 ///
226 /// Non-standard baud rates may not be supported on all systems.
227 BaudOther(usize)
228}
229
230impl BaudRate {
231 /// Creates a `BaudRate` for a particular speed.
232 ///
233 /// This function can be used to select a `BaudRate` variant from an integer containing the
234 /// desired baud rate.
235 ///
236 /// ## Example
237 ///
238 /// ```
239 /// # use serial::BaudRate;
240 /// assert_eq!(BaudRate::Baud9600, BaudRate::from_speed(9600));
241 /// assert_eq!(BaudRate::Baud115200, BaudRate::from_speed(115200));
242 /// assert_eq!(BaudRate::BaudOther(4000000), BaudRate::from_speed(4000000));
243 /// ```
244 pub fn from_speed(speed: usize) -> BaudRate {
245 match speed {
246 110 => BaudRate::Baud110,
247 300 => BaudRate::Baud300,
248 600 => BaudRate::Baud600,
249 1200 => BaudRate::Baud1200,
250 2400 => BaudRate::Baud2400,
251 4800 => BaudRate::Baud4800,
252 9600 => BaudRate::Baud9600,
253 19200 => BaudRate::Baud19200,
254 38400 => BaudRate::Baud38400,
255 57600 => BaudRate::Baud57600,
256 115200 => BaudRate::Baud115200,
257 n => BaudRate::BaudOther(n),
258 }
259 }
260
261 /// Returns the baud rate as an integer.
262 ///
263 /// ## Example
264 ///
265 /// ```
266 /// # use serial::BaudRate;
267 /// assert_eq!(9600, BaudRate::Baud9600.speed());
268 /// assert_eq!(115200, BaudRate::Baud115200.speed());
269 /// assert_eq!(4000000, BaudRate::BaudOther(4000000).speed());
270 /// ```
271 pub fn speed(&self) -> usize {
272 match *self {
273 BaudRate::Baud110 => 110,
274 BaudRate::Baud300 => 300,
275 BaudRate::Baud600 => 600,
276 BaudRate::Baud1200 => 1200,
277 BaudRate::Baud2400 => 2400,
278 BaudRate::Baud4800 => 4800,
279 BaudRate::Baud9600 => 9600,
280 BaudRate::Baud19200 => 19200,
281 BaudRate::Baud38400 => 38400,
282 BaudRate::Baud57600 => 57600,
283 BaudRate::Baud115200 => 115200,
284 BaudRate::BaudOther(n) => n,
285 }
286 }
287}
288
289/// Number of bits per character.
290#[derive(Debug,Copy,Clone,PartialEq,Eq)]
291pub enum CharSize {
292 /** 5 bits per character. */ Bits5,
293 /** 6 bits per character. */ Bits6,
294 /** 7 bits per character. */ Bits7,
295 /** 8 bits per character. */ Bits8
296}
297
298/// Parity checking modes.
299///
300/// When parity checking is enabled (`ParityOdd` or `ParityEven`) an extra bit is transmitted with
301/// each character. The value of the parity bit is arranged so that the number of 1 bits in the
302/// character (including the parity bit) is an even number (`ParityEven`) or an odd number
303/// (`ParityOdd`).
304///
305/// Parity checking is disabled by setting `ParityNone`, in which case parity bits are not
306/// transmitted.
307#[derive(Debug,Copy,Clone,PartialEq,Eq)]
308pub enum Parity {
309 /// No parity bit.
310 ParityNone,
311
312 /// Parity bit sets odd number of 1 bits.
313 ParityOdd,
314
315 /// Parity bit sets even number of 1 bits.
316 ParityEven
317}
318
319/// Number of stop bits.
320///
321/// Stop bits are transmitted after every character.
322#[derive(Debug,Copy,Clone,PartialEq,Eq)]
323pub enum StopBits {
324 /// One stop bit.
325 Stop1,
326
327 /// Two stop bits.
328 Stop2
329}
330
331/// Flow control modes.
332#[derive(Debug,Copy,Clone,PartialEq,Eq)]
333pub enum FlowControl {
334 /// No flow control.
335 FlowNone,
336
337 /// Flow control using XON/XOFF bytes.
338 FlowSoftware,
339
340 /// Flow control using RTS/CTS signals.
341 FlowHardware
342}
343
344/// A trait for implementing serial devices.
345///
346/// This trait is meant to be used to implement new serial port devices. To use a serial port
347/// device, the [`SerialPort`](trait.SerialPort.html) trait should be used instead. Any type that
348/// implements the `SerialDevice` trait will automatically implement the `SerialPort` trait as
349/// well.
350///
351/// To implement a new serial port device, it's necessary to define a type that can manipulate the
352/// serial port device's settings (baud rate, parity mode, etc). This type is defined by the
353/// `Settings` associated type. The current settings should be determined by reading from the
354/// hardware or operating system for every call to `read_settings()`. The settings can then be
355/// manipulated in memory before being commited to the device with `write_settings()`.
356///
357/// Types that implement `SerialDevice` must also implement `std::io::Read` and `std::io::Write`.
358/// The `read()` and `write()` operations of these traits should honor the timeout that has been
359/// set with the most recent successful call to `set_timeout()`. This timeout value should also be
360/// accessible by calling the `timeout()` method.
361///
362/// A serial port device should also provide access to some basic control signals: RTS, DTR, CTS,
363/// DSR, RI, and CD. The values for the control signals are represented as boolean values, with
364/// `true` indicating the the control signal is active.
365///
366/// Lastly, types that implement `SerialDevice` should release any acquired resources when dropped.
367pub trait SerialDevice: io::Read+io::Write {
368 /// A type that implements the settings for the serial port device.
369 ///
370 /// The `Settings` type is used to retrieve and modify the serial port's settings. This type
371 /// should own any native structures used to manipulate the device's settings, but it should
372 /// not cause any changes in the underlying hardware until written to the device with
373 /// `write_settings()`.
374 type Settings: SerialPortSettings;
375
376 /// Returns the device's current settings.
377 ///
378 /// This function attempts to read the current settings from the hardware. The hardware's
379 /// current settings may not match the settings that were most recently written to the hardware
380 /// with `write_settings()`.
381 ///
382 /// ## Errors
383 ///
384 /// This function returns an error if the settings could not be read from the underlying
385 /// hardware:
386 ///
387 /// * `NoDevice` if the device was disconnected.
388 /// * `Io` for any other type of I/O error.
389 fn read_settings(&self) -> ::Result<Self::Settings>;
390
391 /// Applies new settings to the serial device.
392 ///
393 /// This function attempts to apply all settings to the serial device. Some settings may not be
394 /// supported by the underlying hardware, in which case the result is dependent on the
395 /// implementation. A successful return value does not guarantee that all settings were
396 /// appliied successfully. To check which settings were applied by a successful write,
397 /// applications should use the `read_settings()` method to obtain the latest configuration
398 /// state from the device.
399 ///
400 /// ## Errors
401 ///
402 /// This function returns an error if the settings could not be applied to the underlying
403 /// hardware:
404 ///
405 /// * `NoDevice` if the device was disconnected.
406 /// * `InvalidInput` if a setting is not compatible with the underlying hardware.
407 /// * `Io` for any other type of I/O error.
408 fn write_settings(&mut self, settings: &Self::Settings) -> ::Result<()>;
409
410 /// Returns the current timeout.
411 fn timeout(&self) -> Duration;
412
413 /// Sets the timeout for future I/O operations.
414 fn set_timeout(&mut self, timeout: Duration) -> ::Result<()>;
415
416 /// Sets the state of the RTS (Request To Send) control signal.
417 ///
418 /// Setting a value of `true` asserts the RTS control signal. `false` clears the signal.
419 ///
420 /// ## Errors
421 ///
422 /// This function returns an error if the RTS control signal could not be set to the desired
423 /// state on the underlying hardware:
424 ///
425 /// * `NoDevice` if the device was disconnected.
426 /// * `Io` for any other type of I/O error.
427 fn set_rts(&mut self, level: bool) -> ::Result<()>;
428
429 /// Sets the state of the DTR (Data Terminal Ready) control signal.
430 ///
431 /// Setting a value of `true` asserts the DTR control signal. `false` clears the signal.
432 ///
433 /// ## Errors
434 ///
435 /// This function returns an error if the DTR control signal could not be set to the desired
436 /// state on the underlying hardware:
437 ///
438 /// * `NoDevice` if the device was disconnected.
439 /// * `Io` for any other type of I/O error.
440 fn set_dtr(&mut self, level: bool) -> ::Result<()>;
441
442 /// Reads the state of the CTS (Clear To Send) control signal.
443 ///
444 /// This function returns a boolean that indicates whether the CTS control signal is asserted.
445 ///
446 /// ## Errors
447 ///
448 /// This function returns an error if the state of the CTS control signal could not be read
449 /// from the underlying hardware:
450 ///
451 /// * `NoDevice` if the device was disconnected.
452 /// * `Io` for any other type of I/O error.
453 fn read_cts(&mut self) -> ::Result<bool>;
454
455 /// Reads the state of the DSR (Data Set Ready) control signal.
456 ///
457 /// This function returns a boolean that indicates whether the DSR control signal is asserted.
458 ///
459 /// ## Errors
460 ///
461 /// This function returns an error if the state of the DSR control signal could not be read
462 /// from the underlying hardware:
463 ///
464 /// * `NoDevice` if the device was disconnected.
465 /// * `Io` for any other type of I/O error.
466 fn read_dsr(&mut self) -> ::Result<bool>;
467
468 /// Reads the state of the RI (Ring Indicator) control signal.
469 ///
470 /// This function returns a boolean that indicates whether the RI control signal is asserted.
471 ///
472 /// ## Errors
473 ///
474 /// This function returns an error if the state of the RI control signal could not be read from
475 /// the underlying hardware:
476 ///
477 /// * `NoDevice` if the device was disconnected.
478 /// * `Io` for any other type of I/O error.
479 fn read_ri(&mut self) -> ::Result<bool>;
480
481 /// Reads the state of the CD (Carrier Detect) control signal.
482 ///
483 /// This function returns a boolean that indicates whether the CD control signal is asserted.
484 ///
485 /// ## Errors
486 ///
487 /// This function returns an error if the state of the CD control signal could not be read from
488 /// the underlying hardware:
489 ///
490 /// * `NoDevice` if the device was disconnected.
491 /// * `Io` for any other type of I/O error.
492 fn read_cd(&mut self) -> ::Result<bool>;
493}
494
495/// A trait for serial port devices.
496///
497/// Serial port input and output is implemented through the `std::io::Read` and `std::io::Write`
498/// traits. A timeout can be set with the `set_timeout()` method and applies to all subsequent I/O
499/// operations.
500///
501/// The `SerialPort` trait exposes several common control signals. Each control signal is
502/// represented as a boolean, where `true` indicates that the signal is asserted.
503///
504/// The serial port will be closed when the value is dropped.
505pub trait SerialPort: io::Read+io::Write {
506 /// Returns the current timeout.
507 fn timeout(&self) -> Duration;
508
509 /// Sets the timeout for future I/O operations.
510 fn set_timeout(&mut self, timeout: Duration) -> ::Result<()>;
511
512 /// Configures a serial port device.
513 ///
514 /// ## Errors
515 ///
516 /// This function returns an error if the settings could not be applied to the underlying
517 /// hardware:
518 ///
519 /// * `NoDevice` if the device was disconnected.
520 /// * `InvalidInput` if a setting is not compatible with the underlying hardware.
521 /// * `Io` for any other type of I/O error.
522 fn configure(&mut self, settings: &PortSettings) -> ::Result<()>;
523
524 /// Alter the serial port's configuration.
525 ///
526 /// This method expects a function, which takes a mutable reference to the serial port's
527 /// configuration settings. The serial port's current settings, read from the device, are
528 /// yielded to the provided function. After the function returns, any changes made to the
529 /// settings object will be written back to the device.
530 ///
531 /// ## Errors
532 ///
533 /// This function returns an error if the `setup` function returns an error or if there was an
534 /// error while reading or writing the device's configuration settings:
535 ///
536 /// * `NoDevice` if the device was disconnected.
537 /// * `InvalidInput` if a setting is not compatible with the underlying hardware.
538 /// * `Io` for any other type of I/O error.
539 /// * Any error returned by the `setup` function.
540 ///
541 /// ## Example
542 ///
543 /// The following is a function that toggles a serial port's settings between one and two stop
544 /// bits:
545 ///
546 /// ```no_run
547 /// use std::io;
548 /// use serial::prelude::*;
549 ///
550 /// fn toggle_stop_bits<T: SerialPort>(port: &mut T) -> serial::Result<()> {
551 /// port.reconfigure(&|settings| {
552 /// let stop_bits = match settings.stop_bits() {
553 /// Some(serial::Stop1) => serial::Stop2,
554 /// Some(serial::Stop2) | None => serial::Stop1
555 /// };
556 ///
557 /// settings.set_stop_bits(stop_bits);
558 /// Ok(())
559 /// })
560 /// }
561 /// ```
562 fn reconfigure(&mut self, setup: &Fn (&mut SerialPortSettings) -> ::Result<()>) -> ::Result<()>;
563
564 /// Sets the state of the RTS (Request To Send) control signal.
565 ///
566 /// Setting a value of `true` asserts the RTS control signal. `false` clears the signal.
567 ///
568 /// ## Errors
569 ///
570 /// This function returns an error if the RTS control signal could not be set to the desired
571 /// state on the underlying hardware:
572 ///
573 /// * `NoDevice` if the device was disconnected.
574 /// * `Io` for any other type of I/O error.
575 fn set_rts(&mut self, level: bool) -> ::Result<()>;
576
577 /// Sets the state of the DTR (Data Terminal Ready) control signal.
578 ///
579 /// Setting a value of `true` asserts the DTR control signal. `false` clears the signal.
580 ///
581 /// ## Errors
582 ///
583 /// This function returns an error if the DTR control signal could not be set to the desired
584 /// state on the underlying hardware:
585 ///
586 /// * `NoDevice` if the device was disconnected.
587 /// * `Io` for any other type of I/O error.
588 fn set_dtr(&mut self, level: bool) -> ::Result<()>;
589
590 /// Reads the state of the CTS (Clear To Send) control signal.
591 ///
592 /// This function returns a boolean that indicates whether the CTS control signal is asserted.
593 ///
594 /// ## Errors
595 ///
596 /// This function returns an error if the state of the CTS control signal could not be read
597 /// from the underlying hardware:
598 ///
599 /// * `NoDevice` if the device was disconnected.
600 /// * `Io` for any other type of I/O error.
601 fn read_cts(&mut self) -> ::Result<bool>;
602
603 /// Reads the state of the DSR (Data Set Ready) control signal.
604 ///
605 /// This function returns a boolean that indicates whether the DSR control signal is asserted.
606 ///
607 /// ## Errors
608 ///
609 /// This function returns an error if the state of the DSR control signal could not be read
610 /// from the underlying hardware:
611 ///
612 /// * `NoDevice` if the device was disconnected.
613 /// * `Io` for any other type of I/O error.
614 fn read_dsr(&mut self) -> ::Result<bool>;
615
616 /// Reads the state of the RI (Ring Indicator) control signal.
617 ///
618 /// This function returns a boolean that indicates whether the RI control signal is asserted.
619 ///
620 /// ## Errors
621 ///
622 /// This function returns an error if the state of the RI control signal could not be read from
623 /// the underlying hardware:
624 ///
625 /// * `NoDevice` if the device was disconnected.
626 /// * `Io` for any other type of I/O error.
627 fn read_ri(&mut self) -> ::Result<bool>;
628
629 /// Reads the state of the CD (Carrier Detect) control signal.
630 ///
631 /// This function returns a boolean that indicates whether the CD control signal is asserted.
632 ///
633 /// ## Errors
634 ///
635 /// This function returns an error if the state of the CD control signal could not be read from
636 /// the underlying hardware:
637 ///
638 /// * `NoDevice` if the device was disconnected.
639 /// * `Io` for any other type of I/O error.
640 fn read_cd(&mut self) -> ::Result<bool>;
641}
642
643impl<T> SerialPort for T where T: SerialDevice {
644 fn timeout(&self) -> Duration {
645 T::timeout(self)
646 }
647
648 fn set_timeout(&mut self, timeout: Duration) -> ::Result<()> {
649 T::set_timeout(self, timeout)
650 }
651
652 fn configure(&mut self, settings: &PortSettings) -> ::Result<()> {
653 let mut device_settings = try!(T::read_settings(self));
654
655 try!(device_settings.set_baud_rate(settings.baud_rate));
656 device_settings.set_char_size(settings.char_size);
657 device_settings.set_parity(settings.parity);
658 device_settings.set_stop_bits(settings.stop_bits);
659 device_settings.set_flow_control(settings.flow_control);
660
661 T::write_settings(self, &device_settings)
662 }
663
664 fn reconfigure(&mut self, setup: &Fn (&mut SerialPortSettings) -> ::Result<()>) -> ::Result<()> {
665 let mut device_settings = try!(T::read_settings(self));
666 try!(setup(&mut device_settings));
667 T::write_settings(self, &device_settings)
668 }
669
670 fn set_rts(&mut self, level: bool) -> ::Result<()> {
671 T::set_rts(self, level)
672 }
673
674 fn set_dtr(&mut self, level: bool) -> ::Result<()> {
675 T::set_dtr(self, level)
676 }
677
678 fn read_cts(&mut self) -> ::Result<bool> {
679 T::read_cts(self)
680 }
681
682 fn read_dsr(&mut self) -> ::Result<bool> {
683 T::read_dsr(self)
684 }
685
686 fn read_ri(&mut self) -> ::Result<bool> {
687 T::read_ri(self)
688 }
689
690 fn read_cd(&mut self) -> ::Result<bool> {
691 T::read_cd(self)
692 }
693}
694
695/// A trait for objects that implement serial port configurations.
696pub trait SerialPortSettings {
697 /// Returns the current baud rate.
698 ///
699 /// This function returns `None` if the baud rate could not be determined. This may occur if
700 /// the hardware is in an uninitialized state. Setting a baud rate with `set_baud_rate()`
701 /// should initialize the baud rate to a supported value.
702 fn baud_rate(&self) -> Option<BaudRate>;
703
704 /// Returns the character size.
705 ///
706 /// This function returns `None` if the character size could not be determined. This may occur
707 /// if the hardware is in an uninitialized state or is using a non-standard character size.
708 /// Setting a baud rate with `set_char_size()` should initialize the character size to a
709 /// supported value.
710 fn char_size(&self) -> Option<CharSize>;
711
712 /// Returns the parity-checking mode.
713 ///
714 /// This function returns `None` if the parity mode could not be determined. This may occur if
715 /// the hardware is in an uninitialized state or is using a non-standard parity mode. Setting
716 /// a parity mode with `set_parity()` should initialize the parity mode to a supported value.
717 fn parity(&self) -> Option<Parity>;
718
719 /// Returns the number of stop bits.
720 ///
721 /// This function returns `None` if the number of stop bits could not be determined. This may
722 /// occur if the hardware is in an uninitialized state or is using an unsupported stop bit
723 /// configuration. Setting the number of stop bits with `set_stop-bits()` should initialize the
724 /// stop bits to a supported value.
725 fn stop_bits(&self) -> Option<StopBits>;
726
727 /// Returns the flow control mode.
728 ///
729 /// This function returns `None` if the flow control mode could not be determined. This may
730 /// occur if the hardware is in an uninitialized state or is using an unsupported flow control
731 /// mode. Setting a flow control mode with `set_flow_control()` should initialize the flow
732 /// control mode to a supported value.
733 fn flow_control(&self) -> Option<FlowControl>;
734
735 /// Sets the baud rate.
736 ///
737 /// ## Errors
738 ///
739 /// If the implementation does not support the requested baud rate, this function may return an
740 /// `InvalidInput` error. Even if the baud rate is accepted by `set_baud_rate()`, it may not be
741 /// supported by the underlying hardware.
742 fn set_baud_rate(&mut self, baud_rate: BaudRate) -> ::Result<()>;
743
744 /// Sets the character size.
745 fn set_char_size(&mut self, char_size: CharSize);
746
747 /// Sets the parity-checking mode.
748 fn set_parity(&mut self, parity: Parity);
749
750 /// Sets the number of stop bits.
751 fn set_stop_bits(&mut self, stop_bits: StopBits);
752
753 /// Sets the flow control mode.
754 fn set_flow_control(&mut self, flow_control: FlowControl);
755}
756
757/// A device-indepenent implementation of serial port settings.
758#[derive(Debug,Copy,Clone,PartialEq,Eq)]
759pub struct PortSettings {
760 /// Baud rate.
761 pub baud_rate: BaudRate,
762
763 /// Character size.
764 pub char_size: CharSize,
765
766 /// Parity checking mode.
767 pub parity: Parity,
768
769 /// Number of stop bits.
770 pub stop_bits: StopBits,
771
772 /// Flow control mode.
773 pub flow_control: FlowControl
774}
775
776impl Default for PortSettings {
777 fn default() -> Self {
778 PortSettings {
779 baud_rate: BaudRate::Baud9600,
780 char_size: CharSize::Bits8,
781 parity: Parity::ParityNone,
782 stop_bits: StopBits::Stop1,
783 flow_control: FlowControl::FlowNone
784 }
785 }
786}
787
788impl SerialPortSettings for PortSettings {
789 fn baud_rate(&self) -> Option<BaudRate> {
790 Some(self.baud_rate)
791 }
792
793 fn char_size(&self) -> Option<CharSize> {
794 Some(self.char_size)
795 }
796
797 fn parity(&self) -> Option<Parity> {
798 Some(self.parity)
799 }
800
801 fn stop_bits(&self) -> Option<StopBits> {
802 Some(self.stop_bits)
803 }
804
805 fn flow_control(&self) -> Option<FlowControl> {
806 Some(self.flow_control)
807 }
808
809 fn set_baud_rate(&mut self, baud_rate: BaudRate) -> ::Result<()> {
810 self.baud_rate = baud_rate;
811 Ok(())
812 }
813
814 fn set_char_size(&mut self, char_size: CharSize) {
815 self.char_size = char_size;
816 }
817
818 fn set_parity(&mut self, parity: Parity) {
819 self.parity = parity;
820 }
821
822 fn set_stop_bits(&mut self, stop_bits: StopBits) {
823 self.stop_bits = stop_bits;
824 }
825
826 fn set_flow_control(&mut self, flow_control: FlowControl) {
827 self.flow_control = flow_control;
828 }
829}
830
831#[cfg(test)]
832mod tests {
833 use std::default::Default;
834 use super::*;
835
836 #[test]
837 fn port_settings_manipulates_baud_rate() {
838 let mut settings: PortSettings = Default::default();
839 settings.set_baud_rate(Baud115200).unwrap();
840 assert_eq!(settings.baud_rate(), Some(Baud115200));
841 }
842
843 #[test]
844 fn port_settings_manipulates_char_size() {
845 let mut settings: PortSettings = Default::default();
846 settings.set_char_size(Bits7);
847 assert_eq!(settings.char_size(), Some(Bits7));
848 }
849
850 #[test]
851 fn port_settings_manipulates_parity() {
852 let mut settings: PortSettings = Default::default();
853 settings.set_parity(ParityEven);
854 assert_eq!(settings.parity(), Some(ParityEven));
855 }
856
857 #[test]
858 fn port_settings_manipulates_stop_bits() {
859 let mut settings: PortSettings = Default::default();
860 settings.set_stop_bits(Stop2);
861 assert_eq!(settings.stop_bits(), Some(Stop2));
862 }
863
864 #[test]
865 fn port_settings_manipulates_flow_control() {
866 let mut settings: PortSettings = Default::default();
867 settings.set_flow_control(FlowSoftware);
868 assert_eq!(settings.flow_control(), Some(FlowSoftware));
869 }
870}