|
1 | 1 | use core::fmt;
|
2 | 2 |
|
3 |
| -use crate::LineStsFlags; |
| 3 | +use crate::{LineStsFlags, WouldBlockError}; |
4 | 4 |
|
5 | 5 | /// A x86 I/O port-mapped UART.
|
6 | 6 | #[cfg_attr(docsrs, doc(cfg(any(target_arch = "x86", target_arch = "x86_64"))))]
|
@@ -101,37 +101,47 @@ impl SerialPort {
|
101 | 101 |
|
102 | 102 | /// Sends a byte on the serial port.
|
103 | 103 | pub fn send(&mut self, data: u8) {
|
104 |
| - unsafe { |
105 |
| - match data { |
106 |
| - 8 | 0x7F => { |
107 |
| - wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY)); |
108 |
| - x86::io::outb(self.port_data(), 8); |
109 |
| - wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY)); |
110 |
| - x86::io::outb(self.port_data(), b' '); |
111 |
| - wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY)); |
112 |
| - x86::io::outb(self.port_data(), 8); |
113 |
| - } |
114 |
| - _ => { |
115 |
| - wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY)); |
116 |
| - x86::io::outb(self.port_data(), data); |
117 |
| - } |
| 104 | + match data { |
| 105 | + 8 | 0x7F => { |
| 106 | + self.send_raw(8); |
| 107 | + self.send_raw(b' '); |
| 108 | + self.send_raw(8); |
| 109 | + } |
| 110 | + data => { |
| 111 | + self.send_raw(data); |
118 | 112 | }
|
119 | 113 | }
|
120 | 114 | }
|
121 | 115 |
|
122 | 116 | /// Sends a raw byte on the serial port, intended for binary data.
|
123 | 117 | pub fn send_raw(&mut self, data: u8) {
|
124 |
| - unsafe { |
125 |
| - wait_for!(self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY)); |
126 |
| - x86::io::outb(self.port_data(), data); |
| 118 | + retry_until_ok!(self.try_send_raw(data)) |
| 119 | + } |
| 120 | + |
| 121 | + /// Tries to send a raw byte on the serial port, intended for binary data. |
| 122 | + pub fn try_send_raw(&mut self, data: u8) -> Result<(), WouldBlockError> { |
| 123 | + if self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY) { |
| 124 | + unsafe { |
| 125 | + x86::io::outb(self.port_data(), data); |
| 126 | + } |
| 127 | + Ok(()) |
| 128 | + } else { |
| 129 | + Err(WouldBlockError) |
127 | 130 | }
|
128 | 131 | }
|
129 | 132 |
|
130 | 133 | /// Receives a byte on the serial port.
|
131 | 134 | pub fn receive(&mut self) -> u8 {
|
132 |
| - unsafe { |
133 |
| - wait_for!(self.line_sts().contains(LineStsFlags::INPUT_FULL)); |
134 |
| - x86::io::inb(self.port_data()) |
| 135 | + retry_until_ok!(self.try_receive()) |
| 136 | + } |
| 137 | + |
| 138 | + /// Tries to receive a byte on the serial port. |
| 139 | + pub fn try_receive(&mut self) -> Result<u8, WouldBlockError> { |
| 140 | + if self.line_sts().contains(LineStsFlags::INPUT_FULL) { |
| 141 | + let data = unsafe { x86::io::inb(self.port_data()) }; |
| 142 | + Ok(data) |
| 143 | + } else { |
| 144 | + Err(WouldBlockError) |
135 | 145 | }
|
136 | 146 | }
|
137 | 147 | }
|
|
0 commit comments