1 use std::mem::MaybeUninit;
2 use winapi::shared::minwindef::*;
3 use winapi::um::commapi::*;
4 use winapi::um::winbase::*;
5 use winapi::um::winnt::HANDLE;
6
7 use crate::{DataBits, FlowControl, Parity, Result, StopBits};
8
get_dcb(handle: HANDLE) -> Result<DCB>9 pub(crate) fn get_dcb(handle: HANDLE) -> Result<DCB> {
10 let mut dcb: DCB = unsafe { MaybeUninit::zeroed().assume_init() };
11 dcb.DCBlength = std::mem::size_of::<DCB>() as u32;
12
13 if unsafe { GetCommState(handle, &mut dcb) } != 0 {
14 Ok(dcb)
15 } else {
16 Err(super::error::last_os_error())
17 }
18 }
19
20 /// Initialize the DCB struct
21 /// Set all values that won't be affected by `SerialPortBuilder` options.
init(dcb: &mut DCB)22 pub(crate) fn init(dcb: &mut DCB) {
23 // dcb.DCBlength
24 // dcb.BaudRate
25 // dcb.BitFields
26 // dcb.wReserved
27 // dcb.XonLim
28 // dcb.XoffLim
29 // dcb.ByteSize
30 // dcb.Parity
31 // dcb.StopBits
32 dcb.XonChar = 17;
33 dcb.XoffChar = 19;
34 dcb.ErrorChar = '\0' as winapi::ctypes::c_char;
35 dcb.EofChar = 26;
36 // dcb.EvtChar
37 // always true for communications resources
38 dcb.set_fBinary(TRUE as DWORD);
39 // dcb.set_fParity()
40 // dcb.set_fOutxCtsFlow()
41 // serialport-rs doesn't support toggling DSR: so disable fOutxDsrFlow
42 dcb.set_fOutxDsrFlow(FALSE as DWORD);
43 dcb.set_fDtrControl(DTR_CONTROL_DISABLE);
44 // disable because fOutxDsrFlow is disabled as well
45 dcb.set_fDsrSensitivity(FALSE as DWORD);
46 // dcb.set_fTXContinueOnXoff()
47 // dcb.set_fOutX()
48 // dcb.set_fInX()
49 dcb.set_fErrorChar(FALSE as DWORD);
50 // fNull: when set to TRUE null bytes are discarded when received.
51 // null bytes won't be discarded by serialport-rs
52 dcb.set_fNull(FALSE as DWORD);
53 // dcb.set_fRtsControl()
54 // serialport-rs does not handle the fAbortOnError behaviour, so we must make sure it's not enabled
55 dcb.set_fAbortOnError(FALSE as DWORD);
56 }
57
set_dcb(handle: HANDLE, mut dcb: DCB) -> Result<()>58 pub(crate) fn set_dcb(handle: HANDLE, mut dcb: DCB) -> Result<()> {
59 if unsafe { SetCommState(handle, &mut dcb as *mut _) != 0 } {
60 Ok(())
61 } else {
62 Err(super::error::last_os_error())
63 }
64 }
65
set_baud_rate(dcb: &mut DCB, baud_rate: u32)66 pub(crate) fn set_baud_rate(dcb: &mut DCB, baud_rate: u32) {
67 dcb.BaudRate = baud_rate as DWORD;
68 }
69
set_data_bits(dcb: &mut DCB, data_bits: DataBits)70 pub(crate) fn set_data_bits(dcb: &mut DCB, data_bits: DataBits) {
71 dcb.ByteSize = match data_bits {
72 DataBits::Five => 5,
73 DataBits::Six => 6,
74 DataBits::Seven => 7,
75 DataBits::Eight => 8,
76 };
77 }
78
set_parity(dcb: &mut DCB, parity: Parity)79 pub(crate) fn set_parity(dcb: &mut DCB, parity: Parity) {
80 dcb.Parity = match parity {
81 Parity::None => NOPARITY,
82 Parity::Odd => ODDPARITY,
83 Parity::Even => EVENPARITY,
84 };
85
86 dcb.set_fParity(if parity == Parity::None { FALSE } else { TRUE } as DWORD);
87 }
88
set_stop_bits(dcb: &mut DCB, stop_bits: StopBits)89 pub(crate) fn set_stop_bits(dcb: &mut DCB, stop_bits: StopBits) {
90 dcb.StopBits = match stop_bits {
91 StopBits::One => ONESTOPBIT,
92 StopBits::Two => TWOSTOPBITS,
93 };
94 }
95
set_flow_control(dcb: &mut DCB, flow_control: FlowControl)96 pub(crate) fn set_flow_control(dcb: &mut DCB, flow_control: FlowControl) {
97 match flow_control {
98 FlowControl::None => {
99 dcb.set_fOutxCtsFlow(0);
100 dcb.set_fRtsControl(0);
101 dcb.set_fOutX(0);
102 dcb.set_fInX(0);
103 }
104 FlowControl::Software => {
105 dcb.set_fOutxCtsFlow(0);
106 dcb.set_fRtsControl(0);
107 dcb.set_fOutX(1);
108 dcb.set_fInX(1);
109 }
110 FlowControl::Hardware => {
111 dcb.set_fOutxCtsFlow(1);
112 dcb.set_fRtsControl(1);
113 dcb.set_fOutX(0);
114 dcb.set_fInX(0);
115 }
116 }
117 }
118