-
-
Notifications
You must be signed in to change notification settings - Fork 170
/
Copy pathserial.rs
113 lines (101 loc) · 3.92 KB
/
serial.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Abstraction over byte stream devices, also known as serial I/O devices.
use crate::proto::unsafe_protocol;
use crate::{Result, StatusExt};
use core::fmt::Write;
use uefi_raw::protocol::console::serial::SerialIoProtocol;
pub use uefi_raw::protocol::console::serial::{
ControlBits, Parity, SerialIoMode as IoMode, StopBits,
};
/// Serial IO [`Protocol`]. Provides access to a serial I/O device.
///
/// This can include standard UART devices, serial ports over a USB interface,
/// or any other character-based communication device.
///
/// Since UEFI drivers are implemented through polling, if you fail to regularly
/// check for input/output, some data might be lost.
///
/// [`Protocol`]: uefi::proto::Protocol
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol(SerialIoProtocol::GUID)]
pub struct Serial(SerialIoProtocol);
impl Serial {
/// Reset the device.
pub fn reset(&mut self) -> Result {
unsafe { (self.0.reset)(&mut self.0) }.to_result()
}
/// Returns the current I/O mode.
#[must_use]
pub const fn io_mode(&self) -> &IoMode {
unsafe { &*self.0.mode }
}
/// Sets the device's new attributes.
///
/// The given `IoMode` will become the device's new `IoMode`,
/// with some exceptions:
///
/// - `control_mask` is ignored, since it's a read-only field;
///
/// - values set to `0` / `Default` will be filled with the device's
/// default parameters
///
/// - if either `baud_rate` or `receive_fifo_depth` is less than
/// the device's minimum, an error will be returned;
/// this value will be rounded down to the nearest value supported by the device;
pub fn set_attributes(&mut self, mode: &IoMode) -> Result {
unsafe {
(self.0.set_attributes)(
&mut self.0,
mode.baud_rate,
mode.receive_fifo_depth,
mode.timeout,
mode.parity,
mode.data_bits as u8,
mode.stop_bits,
)
}
.to_result()
}
/// Retrieve the device's current control bits.
pub fn get_control_bits(&self) -> Result<ControlBits> {
let mut bits = ControlBits::empty();
unsafe { (self.0.get_control_bits)(&self.0, &mut bits) }.to_result_with_val(|| bits)
}
/// Sets the device's new control bits.
///
/// Not all bits can be modified with this function. A mask of the allowed
/// bits is stored in the [`ControlBits::SETTABLE`] constant.
pub fn set_control_bits(&mut self, bits: ControlBits) -> Result {
unsafe { (self.0.set_control_bits)(&mut self.0, bits) }.to_result()
}
/// Reads data from this device.
///
/// This operation will block until the buffer has been filled with data or
/// an error occurs. In the latter case, the error will indicate how many
/// bytes were actually read from the device.
pub fn read(&mut self, data: &mut [u8]) -> Result<(), usize> {
let mut buffer_size = data.len();
unsafe { (self.0.read)(&mut self.0, &mut buffer_size, data.as_mut_ptr()) }.to_result_with(
|| debug_assert_eq!(buffer_size, data.len()),
|_| buffer_size,
)
}
/// Writes data to this device.
///
/// This operation will block until the data has been fully written or an
/// error occurs. In the latter case, the error will indicate how many bytes
/// were actually written to the device.
pub fn write(&mut self, data: &[u8]) -> Result<(), usize> {
let mut buffer_size = data.len();
unsafe { (self.0.write)(&mut self.0, &mut buffer_size, data.as_ptr()) }.to_result_with(
|| debug_assert_eq!(buffer_size, data.len()),
|_| buffer_size,
)
}
}
impl Write for Serial {
fn write_str(&mut self, s: &str) -> core::fmt::Result {
self.write(s.as_bytes()).map_err(|_| core::fmt::Error)
}
}