summaryrefslogtreecommitdiffstats
path: root/src/ps2.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ps2.rs55
1 files changed, 21 insertions, 34 deletions
diff --git a/src/ps2.rs b/src/ps2.rs
index e972658..3a42c1a 100644
--- a/src/ps2.rs
+++ b/src/ps2.rs
@@ -179,47 +179,34 @@ fn drain_input() {
179 } 179 }
180} 180}
181 181
182/// Poll for a key event. Blocks until a key is pressed. 182/// Poll for a key event. Blocks via `hlt` until a key is pressed.
183/// The keyboard interrupt handler pushes raw scancodes to a ring buffer;
184/// this function pops and decodes them.
183pub fn poll_key() -> KeyEvent { 185pub fn poll_key() -> KeyEvent {
184 loop { 186 loop {
185 let byte = read_data(); 187 // Disable interrupts so the buffer-empty → hlt window is atomic.
186 if let Some(ev) = process_byte(byte) { 188 unsafe { core::arch::asm!("cli", options(nostack, preserves_flags)); }
187 return ev;
188 }
189 }
190}
191 189
192/// Non-blocking poll. 190 if let Some(byte) = crate::interrupts::read_scancode() {
193pub fn try_poll_key() -> Option<KeyEvent> { 191 unsafe { core::arch::asm!("sti", options(nostack, preserves_flags)); }
194 unsafe { 192 if let Some(ev) = process_byte(byte) {
195 let status: u8; 193 return ev;
196 core::arch::asm!("in al, dx", out("al") status, in("dx") STATUS_PORT, 194 }
197 options(nostack, preserves_flags)); 195 } else {
198 if status & STAT_OUTPUT_FULL == 0 { 196 // Re-enable and halt. If a keyboard IRQ arrived between the
199 return None; 197 // buffer check and `sti`, the CPU sees a pending interrupt
198 // and `hlt` returns immediately.
199 unsafe {
200 core::arch::asm!("sti; hlt", options(nostack, preserves_flags));
201 }
200 } 202 }
201 let data: u8;
202 core::arch::asm!("in al, dx", out("al") data, in("dx") DATA_PORT,
203 options(nostack, preserves_flags));
204 process_byte(data)
205 } 203 }
206} 204}
207 205
208/// Read a byte from the keyboard data port (blocking). 206/// Non-blocking poll — read from the interrupt ring buffer if available.
209fn read_data() -> u8 { 207pub fn try_poll_key() -> Option<KeyEvent> {
210 unsafe { 208 let byte = crate::interrupts::read_scancode()?;
211 loop { 209 process_byte(byte)
212 let status: u8;
213 core::arch::asm!("in al, dx", out("al") status, in("dx") STATUS_PORT,
214 options(nostack, preserves_flags));
215 if status & STAT_OUTPUT_FULL != 0 {
216 let data: u8;
217 core::arch::asm!("in al, dx", out("al") data, in("dx") DATA_PORT,
218 options(nostack, preserves_flags));
219 return data;
220 }
221 }
222 }
223} 210}
224 211
225/// Process a single scancode byte. Returns Some(KeyEvent) when a visible 212/// Process a single scancode byte. Returns Some(KeyEvent) when a visible