|
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