1 use crate::{guid, Guid, Status};
2 use bitflags::bitflags;
3 
4 bitflags! {
5     /// The control bits of a device. These are defined in the [RS-232] standard.
6     ///
7     /// [RS-232]: https://en.wikipedia.org/wiki/RS-232
8     #[repr(transparent)]
9     #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
10     pub struct ControlBits: u32 {
11         /// Clear to send
12         const CLEAR_TO_SEND = 0x10;
13         /// Data set ready
14         const DATA_SET_READY = 0x20;
15         /// Indicates that a phone line is ringing
16         const RING_INDICATE = 0x40;
17         /// Indicates the connection is still connected
18         const CARRIER_DETECT = 0x80;
19         /// The input buffer is empty
20         const INPUT_BUFFER_EMPTY = 0x100;
21         /// The output buffer is empty
22         const OUTPUT_BUFFER_EMPTY = 0x200;
23 
24         /// Terminal is ready for communications
25         const DATA_TERMINAL_READY = 0x1;
26         /// Request the device to send data
27         const REQUEST_TO_SEND = 0x2;
28         /// Enable hardware loop-back
29         const HARDWARE_LOOPBACK_ENABLE = 0x1000;
30         /// Enable software loop-back
31         const SOFTWARE_LOOPBACK_ENABLE = 0x2000;
32         /// Allow the hardware to handle flow control
33         const HARDWARE_FLOW_CONTROL_ENABLE = 0x4000;
34 
35         /// Bitmask of the control bits that can be set.
36         ///
37         /// Up to date as of UEFI 2.7 / Serial protocol v1
38         const SETTABLE =
39             ControlBits::DATA_TERMINAL_READY.bits()
40             | ControlBits::REQUEST_TO_SEND.bits()
41             | ControlBits::HARDWARE_LOOPBACK_ENABLE.bits()
42             | ControlBits::SOFTWARE_LOOPBACK_ENABLE.bits()
43             | ControlBits::HARDWARE_FLOW_CONTROL_ENABLE.bits();
44     }
45 }
46 
47 /// Structure representing the device's current parameters.
48 ///
49 /// The default values for all UART-like devices is:
50 /// - 115,200 baud
51 /// - 1 byte receive FIFO
52 /// - 1'000'000 microsecond timeout
53 /// - no parity
54 /// - 8 data bits
55 /// - 1 stop bit
56 ///
57 /// The software is responsible for flow control.
58 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
59 #[repr(C)]
60 pub struct SerialIoMode {
61     /// Bitmask of the control bits that this device supports.
62     pub control_mask: ControlBits,
63     /// If applicable, the number of microseconds to wait before assuming an
64     /// operation timed out.
65     pub timeout: u32,
66     /// Device's baud rate, or 0 if unknown.
67     pub baud_rate: u64,
68     /// Size in character's of the device's buffer.
69     pub receive_fifo_depth: u32,
70     /// Number of data bits in each character.
71     pub data_bits: u32,
72     /// If applicable, the parity that is computed or checked for each character.
73     pub parity: Parity,
74     /// If applicable, the number of stop bits per character.
75     pub stop_bits: StopBits,
76 }
77 
78 #[derive(Debug)]
79 #[repr(C)]
80 pub struct SerialIoProtocol {
81     pub revision: u32,
82     pub reset: unsafe extern "efiapi" fn(*mut Self) -> Status,
83     pub set_attributes: unsafe extern "efiapi" fn(
84         *const Self,
85         baud_rate: u64,
86         receive_fifo_depth: u32,
87         timeout: u32,
88         parity: Parity,
89         data_bits: u8,
90         stop_bits_type: StopBits,
91     ) -> Status,
92     pub set_control_bits: unsafe extern "efiapi" fn(*mut Self, ControlBits) -> Status,
93     pub get_control_bits: unsafe extern "efiapi" fn(*const Self, *mut ControlBits) -> Status,
94     pub write: unsafe extern "efiapi" fn(*mut Self, *mut usize, *const u8) -> Status,
95     pub read: unsafe extern "efiapi" fn(*mut Self, *mut usize, *mut u8) -> Status,
96     pub mode: *const SerialIoMode,
97 }
98 
99 impl SerialIoProtocol {
100     pub const GUID: Guid = guid!("bb25cf6f-f1d4-11d2-9a0c-0090273fc1fd");
101     pub const REVISION: u32 = 0x00010000;
102     pub const REVISION1P1: u32 = 0x00010001;
103 }
104 
105 newtype_enum! {
106     /// The parity of the device.
107     pub enum Parity: u32 => {
108         /// Device default
109         DEFAULT = 0,
110         /// No parity
111         NONE = 1,
112         /// Even parity
113         EVEN = 2,
114         /// Odd parity
115         ODD = 3,
116         /// Mark parity
117         MARK = 4,
118         /// Space parity
119         SPACE = 5,
120     }
121 }
122 
123 newtype_enum! {
124     /// Number of stop bits per character.
125     pub enum StopBits: u32 => {
126         /// Device default
127         DEFAULT = 0,
128         /// 1 stop bit
129         ONE = 1,
130         /// 1.5 stop bits
131         ONE_FIVE = 2,
132         /// 2 stop bits
133         TWO = 3,
134     }
135 }
136